@7365admin1/core 2.29.0 → 2.30.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
@@ -168,6 +168,7 @@ __export(src_exports, {
168
168
  occurrence_book_namespace_collection: () => occurrence_book_namespace_collection,
169
169
  orgSchema: () => orgSchema,
170
170
  overnight_parking_requests_namespace_collection: () => overnight_parking_requests_namespace_collection,
171
+ parseDahuaFind: () => parseDahuaFind,
171
172
  pestDashboardCollection: () => pestDashboardCollection,
172
173
  poolDashboardCollection: () => poolDashboardCollection,
173
174
  promoCodeSchema: () => promoCodeSchema,
@@ -1812,7 +1813,7 @@ var import_node_server_utils8 = require("@7365admin1/node-server-utils");
1812
1813
  var import_mongodb6 = require("mongodb");
1813
1814
  var import_joi5 = __toESM(require("joi"));
1814
1815
  var schemaOccurrenceEntry = import_joi5.default.object({
1815
- site: import_joi5.default.string().hex().required(),
1816
+ site: import_joi5.default.string().hex().length(24).required(),
1816
1817
  dailyOccurrenceBookId: import_joi5.default.string().hex().optional().allow(null, ""),
1817
1818
  serialNumber: import_joi5.default.string().optional().allow(null, ""),
1818
1819
  date: import_joi5.default.date().iso().optional().allow(null, ""),
@@ -1824,14 +1825,14 @@ var schemaOccurrenceEntry = import_joi5.default.object({
1824
1825
  createdByName: import_joi5.default.string().optional().allow(null, "")
1825
1826
  });
1826
1827
  var schemaUpdateOccurrenceEntry = import_joi5.default.object({
1827
- _id: import_joi5.default.string().hex().required(),
1828
+ _id: import_joi5.default.string().hex().length(24).required(),
1828
1829
  serialNumber: import_joi5.default.string().optional().allow(null, ""),
1829
1830
  date: import_joi5.default.date().iso().optional().allow(null, ""),
1830
1831
  subject: import_joi5.default.string().hex().optional().allow(null, ""),
1831
1832
  occurrence: import_joi5.default.string().optional().allow(null, ""),
1832
1833
  signature: import_joi5.default.string().hex().optional().allow(null, ""),
1833
1834
  incidentReportId: import_joi5.default.string().hex().optional().allow(null, ""),
1834
- eSignature: import_joi5.default.string().required(),
1835
+ eSignature: import_joi5.default.string().hex().length(24).required(),
1835
1836
  createdByName: import_joi5.default.string().optional().allow(null, "")
1836
1837
  });
1837
1838
  function MOccurrenceEntry(value) {
@@ -1877,6 +1878,13 @@ function MOccurrenceEntry(value) {
1877
1878
  throw new Error("Invalid incident report ID.");
1878
1879
  }
1879
1880
  }
1881
+ if (value.eSignature && typeof value.eSignature === "string") {
1882
+ try {
1883
+ value.eSignature = new import_mongodb6.ObjectId(value.eSignature);
1884
+ } catch {
1885
+ throw new Error("Invalid incident report ID.");
1886
+ }
1887
+ }
1880
1888
  return {
1881
1889
  _id: value._id ?? new import_mongodb6.ObjectId(),
1882
1890
  site: value.site,
@@ -13099,6 +13107,7 @@ var PersonTypes = /* @__PURE__ */ ((PersonTypes3) => {
13099
13107
  PersonTypes3["GUEST"] = "guest";
13100
13108
  PersonTypes3["TENANT"] = "tenant";
13101
13109
  PersonTypes3["RESIDENT"] = "resident";
13110
+ PersonTypes3["VISITOR"] = "visitor";
13102
13111
  return PersonTypes3;
13103
13112
  })(PersonTypes || {});
13104
13113
  var PersonStatus = /* @__PURE__ */ ((PersonStatus2) => {
@@ -13276,7 +13285,7 @@ var schemaVisitorTransaction = import_joi36.default.object({
13276
13285
  checkIn: import_joi36.default.date().optional().allow(null, ""),
13277
13286
  checkOut: import_joi36.default.date().optional().allow(null, ""),
13278
13287
  deliveryType: import_joi36.default.string().optional().allow(null, ""),
13279
- status: import_joi36.default.string().optional().valid(...Object.values(VisitorStatus)).default("registered" /* REGISTERED */),
13288
+ status: import_joi36.default.string().optional().valid(...Object.values(VisitorStatus)).default("pending" /* PENDING */),
13280
13289
  remarks: import_joi36.default.string().optional().allow(null, ""),
13281
13290
  members: import_joi36.default.array().items(
13282
13291
  import_joi36.default.object({
@@ -13286,7 +13295,6 @@ var schemaVisitorTransaction = import_joi36.default.object({
13286
13295
  contact: import_joi36.default.string().optional().allow(null, "")
13287
13296
  })
13288
13297
  ).optional().allow(null),
13289
- visitorPass: import_joi36.default.string().optional().allow(null, ""),
13290
13298
  unitName: import_joi36.default.string().optional().allow(null, ""),
13291
13299
  expiredAt: import_joi36.default.date().iso().optional().allow(null, ""),
13292
13300
  arrivalTime: import_joi36.default.string().pattern(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().allow(null, "").messages({
@@ -13295,7 +13303,15 @@ var schemaVisitorTransaction = import_joi36.default.object({
13295
13303
  duration: import_joi36.default.number().integer().optional().allow(null),
13296
13304
  isOvernightParking: import_joi36.default.boolean().optional().default(false),
13297
13305
  email: import_joi36.default.string().email().optional().allow(null, ""),
13298
- numberOfPassengers: import_joi36.default.number().integer().optional().allow(null, "")
13306
+ numberOfPassengers: import_joi36.default.number().integer().optional().allow(null, ""),
13307
+ visitorPass: import_joi36.default.array().items(
13308
+ import_joi36.default.string().hex().length(24).optional().allow(null)
13309
+ ),
13310
+ passKeys: import_joi36.default.array().items(
13311
+ import_joi36.default.string().hex().length(24).optional().allow(null)
13312
+ ),
13313
+ checkInRemarks: import_joi36.default.string().optional().allow("", null),
13314
+ checkOutRemarks: import_joi36.default.string().optional().allow("", null)
13299
13315
  });
13300
13316
  var schemaUpdateVisTrans = import_joi36.default.object({
13301
13317
  _id: import_joi36.default.string().hex().length(24).required(),
@@ -13321,7 +13337,15 @@ var schemaUpdateVisTrans = import_joi36.default.object({
13321
13337
  status: import_joi36.default.string().optional().allow(null, ""),
13322
13338
  remarks: import_joi36.default.string().optional().allow(null, ""),
13323
13339
  manualCheckout: import_joi36.default.boolean().optional().allow(null),
13324
- expiredAt: import_joi36.default.date().iso().optional().allow(null, "")
13340
+ expiredAt: import_joi36.default.date().iso().optional().allow(null, ""),
13341
+ visitorPass: import_joi36.default.array().items(
13342
+ import_joi36.default.string().hex().length(24).optional().allow(null)
13343
+ ),
13344
+ passKeys: import_joi36.default.array().items(
13345
+ import_joi36.default.string().hex().length(24).optional().allow(null)
13346
+ ),
13347
+ checkInRemarks: import_joi36.default.string().optional().allow("", null),
13348
+ checkOutRemarks: import_joi36.default.string().optional().allow("", null)
13325
13349
  });
13326
13350
  function MVisitorTransaction(value) {
13327
13351
  const { error } = schemaVisitorTransaction.validate(value, {
@@ -13365,6 +13389,14 @@ function MVisitorTransaction(value) {
13365
13389
  throw new Error("Invalid type for manualCheckout key.");
13366
13390
  }
13367
13391
  }
13392
+ if (value.visitorPass && Array.isArray(value.visitorPass) && value.visitorPass.length > 0)
13393
+ value.visitorPass = value.visitorPass.map(
13394
+ (v) => typeof v === "string" ? new import_mongodb39.ObjectId(v) : v
13395
+ );
13396
+ if (value.passKeys && Array.isArray(value.passKeys) && value.passKeys.length > 0)
13397
+ value.passKeys = value.passKeys.map(
13398
+ (p) => typeof p === "string" ? new import_mongodb39.ObjectId(p) : p
13399
+ );
13368
13400
  const newDate = (/* @__PURE__ */ new Date()).toISOString();
13369
13401
  return {
13370
13402
  _id: value._id,
@@ -13391,7 +13423,10 @@ function MVisitorTransaction(value) {
13391
13423
  contractorType: value.contractorType,
13392
13424
  manualCheckout: value.manualCheckout ?? false,
13393
13425
  direction: value.direction,
13394
- visitorPass: value.visitorPass,
13426
+ visitorPass: value.visitorPass ?? [],
13427
+ passKeys: value.passKeys ?? [],
13428
+ checkInRemarks: value.checkInRemarks,
13429
+ checkOutRemarks: value.checkOutRemarks,
13395
13430
  unitName: value.unitName,
13396
13431
  expiredAt: value.expiredAt ?? null,
13397
13432
  createdAt: value.createdAt ?? newDate,
@@ -13409,9 +13444,6 @@ function useVisitorTransactionRepo() {
13409
13444
  throw new import_node_server_utils68.InternalServerError("Unable to connect to server.");
13410
13445
  }
13411
13446
  const collection = db.collection(visitors_namespace_collection);
13412
- const { delNamespace, getCache, setCache } = (0, import_node_server_utils68.useCache)(
13413
- visitors_namespace_collection
13414
- );
13415
13447
  async function createTextIndex() {
13416
13448
  try {
13417
13449
  await collection.createIndex({
@@ -13432,16 +13464,6 @@ function useVisitorTransactionRepo() {
13432
13464
  try {
13433
13465
  value = MVisitorTransaction(value);
13434
13466
  const res = await collection.insertOne(value, { session });
13435
- delNamespace().then(() => {
13436
- import_node_server_utils68.logger.info(
13437
- `Cache cleared for namespace: ${visitors_namespace_collection}`
13438
- );
13439
- }).catch((err) => {
13440
- import_node_server_utils68.logger.error(
13441
- `Failed to clear cache for namespace: ${visitors_namespace_collection}`,
13442
- err
13443
- );
13444
- });
13445
13467
  return res.insertedId;
13446
13468
  } catch (error) {
13447
13469
  const isDuplicated = error.message.includes("duplicate");
@@ -13464,7 +13486,7 @@ function useVisitorTransactionRepo() {
13464
13486
  type = "",
13465
13487
  checkedOut,
13466
13488
  plateNumber = ""
13467
- }, session) {
13489
+ }) {
13468
13490
  page = page > 0 ? page - 1 : 0;
13469
13491
  const skip = page * limit;
13470
13492
  let checkOutFilter;
@@ -13499,26 +13521,6 @@ function useVisitorTransactionRepo() {
13499
13521
  ...plateNumber && { plateNumber }
13500
13522
  };
13501
13523
  sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
13502
- const cacheOptions = {
13503
- status,
13504
- page,
13505
- limit,
13506
- sort: JSON.stringify(sort),
13507
- ...search && { search },
13508
- ...query.org && { org: query.org.toString() },
13509
- ...query.site && { site: query.site.toString() },
13510
- ...checkIn && { checkIn: JSON.stringify(checkIn) },
13511
- ...checkOutFilter && { checkOut: JSON.stringify(checkOutFilter) },
13512
- ...type && (Array.isArray(type) ? { type: JSON.stringify(type) } : { type }),
13513
- ...checkedOut !== void 0 && { checkedOut },
13514
- ...plateNumber && { plateNumber }
13515
- };
13516
- const cacheKey = (0, import_node_server_utils68.makeCacheKey)(visitors_namespace_collection, cacheOptions);
13517
- const cachedData = await getCache(cacheKey);
13518
- if (cachedData) {
13519
- import_node_server_utils68.logger.info(`Cache hit for key: ${cacheKey}`);
13520
- return cachedData;
13521
- }
13522
13524
  try {
13523
13525
  const basePipeline = [{ $match: query }];
13524
13526
  const [items, countResult] = await Promise.all([
@@ -13562,23 +13564,12 @@ function useVisitorTransactionRepo() {
13562
13564
  ]);
13563
13565
  const totalCount = countResult[0]?.total || 0;
13564
13566
  const data = (0, import_node_server_utils68.paginate)(items, page, limit, totalCount);
13565
- setCache(cacheKey, data, 15 * 60).then(() => {
13566
- import_node_server_utils68.logger.info(`Cache set for key: ${cacheKey}`);
13567
- }).catch((err) => {
13568
- import_node_server_utils68.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
13569
- });
13570
13567
  return data;
13571
13568
  } catch (error) {
13572
13569
  throw error;
13573
13570
  }
13574
13571
  }
13575
13572
  async function getVisitorTransactionById(id) {
13576
- const cacheKey = (0, import_node_server_utils68.makeCacheKey)(visitors_namespace_collection, { id });
13577
- const cachedData = await getCache(cacheKey);
13578
- if (cachedData) {
13579
- import_node_server_utils68.logger.info(`Cache hit for key: ${cacheKey}`);
13580
- return cachedData;
13581
- }
13582
13573
  const _id = (0, import_node_server_utils68.toObjectId)(id);
13583
13574
  try {
13584
13575
  const basePipeline = [{ $match: { _id } }];
@@ -13615,38 +13606,20 @@ function useVisitorTransactionRepo() {
13615
13606
  }
13616
13607
  }
13617
13608
  ]).toArray();
13618
- setCache(cacheKey, result, 15 * 60).then(() => {
13619
- import_node_server_utils68.logger.info(`Cache set for key: ${cacheKey}`);
13620
- }).catch((err) => {
13621
- import_node_server_utils68.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
13622
- });
13623
13609
  return result;
13624
13610
  } catch (error) {
13625
13611
  throw error;
13626
13612
  }
13627
13613
  }
13628
13614
  async function getOpenByPlateNumber(plateNumber, site) {
13629
- const _site = typeof site === "string" ? site : (0, import_node_server_utils68.toObjectId)(site);
13630
- const cacheKey = (0, import_node_server_utils68.makeCacheKey)(visitors_namespace_collection, {
13615
+ const _site = typeof site === "string" ? (0, import_node_server_utils68.toObjectId)(site) : site;
13616
+ const query = {
13631
13617
  plateNumber,
13632
- key: "get-open-transaction-plate-number",
13633
- site
13634
- });
13618
+ site: _site,
13619
+ checkOut: null
13620
+ };
13635
13621
  try {
13636
- const cacheData = await getCache(cacheKey);
13637
- if (cacheData) {
13638
- import_node_server_utils68.logger.info(`Cache hit for key: ${cacheKey}`);
13639
- return cacheData;
13640
- }
13641
- const data = await collection.findOne(
13642
- { plateNumber, site: _site, checkOut: null },
13643
- { sort: { _id: -1 } }
13644
- );
13645
- setCache(cacheKey, data, 15 * 60).then(() => {
13646
- import_node_server_utils68.logger.info(`Cache set for key: ${cacheKey}`);
13647
- }).catch((err) => {
13648
- import_node_server_utils68.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
13649
- });
13622
+ const data = await collection.findOne(query);
13650
13623
  return data;
13651
13624
  } catch (error) {
13652
13625
  throw new import_node_server_utils68.InternalServerError(
@@ -13670,16 +13643,6 @@ function useVisitorTransactionRepo() {
13670
13643
  { $set: value },
13671
13644
  { session }
13672
13645
  );
13673
- delNamespace().then(() => {
13674
- import_node_server_utils68.logger.info(
13675
- `Cache cleared for namespace: ${visitors_namespace_collection}`
13676
- );
13677
- }).catch((err) => {
13678
- import_node_server_utils68.logger.error(
13679
- `Failed to clear cache for namespace: ${visitors_namespace_collection}`,
13680
- err
13681
- );
13682
- });
13683
13646
  return result;
13684
13647
  } catch (error) {
13685
13648
  throw error;
@@ -13701,16 +13664,6 @@ function useVisitorTransactionRepo() {
13701
13664
  if (res.modifiedCount === 0) {
13702
13665
  throw new import_node_server_utils68.InternalServerError("Unable to delete visitor transaction.");
13703
13666
  }
13704
- delNamespace().then(() => {
13705
- import_node_server_utils68.logger.info(
13706
- `Cache cleared for namespace: ${visitors_namespace_collection}`
13707
- );
13708
- }).catch((err) => {
13709
- import_node_server_utils68.logger.error(
13710
- `Failed to clear cache for namespace: ${visitors_namespace_collection}`,
13711
- err
13712
- );
13713
- });
13714
13667
  return res.modifiedCount;
13715
13668
  } catch (error) {
13716
13669
  throw error;
@@ -13776,16 +13729,6 @@ function useVisitorTransactionRepo() {
13776
13729
  },
13777
13730
  { session }
13778
13731
  );
13779
- delNamespace().then(() => {
13780
- import_node_server_utils68.logger.info(
13781
- `Cache cleared for namespace: ${visitors_namespace_collection}`
13782
- );
13783
- }).catch((err) => {
13784
- import_node_server_utils68.logger.error(
13785
- `Failed to clear cache for namespace: ${visitors_namespace_collection}`,
13786
- err
13787
- );
13788
- });
13789
13732
  return res;
13790
13733
  } catch (error) {
13791
13734
  throw error;
@@ -13817,6 +13760,7 @@ var VehicleType = /* @__PURE__ */ ((VehicleType2) => {
13817
13760
  var VehicleCategory = /* @__PURE__ */ ((VehicleCategory2) => {
13818
13761
  VehicleCategory2["RESIDENT"] = "resident";
13819
13762
  VehicleCategory2["VISITOR"] = "visitor";
13763
+ VehicleCategory2["GUEST"] = "guest";
13820
13764
  return VehicleCategory2;
13821
13765
  })(VehicleCategory || {});
13822
13766
  var VehicleStatus = /* @__PURE__ */ ((VehicleStatus2) => {
@@ -13861,7 +13805,7 @@ var vehicleSchema = import_joi37.default.object({
13861
13805
  return value;
13862
13806
  }).required(),
13863
13807
  type: import_joi37.default.string().required().valid(...Object.values(VehicleType)),
13864
- category: import_joi37.default.string().required().valid(...Object.values(VehicleCategory)),
13808
+ category: import_joi37.default.string().required().valid(...Object.values(PersonTypes)),
13865
13809
  name: import_joi37.default.string().required(),
13866
13810
  phoneNumber: import_joi37.default.string().optional().allow("", null),
13867
13811
  recNo: import_joi37.default.string().optional().allow("", null),
@@ -14005,9 +13949,6 @@ function useVehicleRepo() {
14005
13949
  throw new import_node_server_utils70.InternalServerError("Unable to connect to server.");
14006
13950
  }
14007
13951
  const collection = db.collection(vehicles_namespace_collection);
14008
- const { delNamespace, setCache, getCache } = (0, import_node_server_utils70.useCache)(
14009
- vehicles_namespace_collection
14010
- );
14011
13952
  async function createIndex() {
14012
13953
  try {
14013
13954
  await collection.createIndexes([
@@ -14039,16 +13980,6 @@ function useVehicleRepo() {
14039
13980
  try {
14040
13981
  value = MVehicle(value);
14041
13982
  const res = await collection.insertOne(value, { session });
14042
- delNamespace().then(() => {
14043
- import_node_server_utils70.logger.info(
14044
- `Cache cleared for namespace: ${vehicles_namespace_collection}`
14045
- );
14046
- }).catch((err) => {
14047
- import_node_server_utils70.logger.error(
14048
- `Failed to clear cache for namespace: ${vehicles_namespace_collection}`,
14049
- err
14050
- );
14051
- });
14052
13983
  return res.insertedId;
14053
13984
  } catch (error) {
14054
13985
  import_node_server_utils70.logger.log({
@@ -14073,29 +14004,12 @@ function useVehicleRepo() {
14073
14004
  }) {
14074
14005
  page = page > 0 ? page - 1 : 0;
14075
14006
  const baseQuery = {
14076
- ...status && { status },
14077
- ...type && { type },
14078
- ...category && { category }
14079
- };
14080
- let query = { ...baseQuery };
14081
- const cacheOptions = {
14082
14007
  ...status && { status },
14083
14008
  ...type && { type },
14084
14009
  ...category && { category },
14085
- page: String(page),
14086
- limit: String(limit),
14087
- sort: JSON.stringify(sort)
14010
+ ...search && { $text: { search } }
14088
14011
  };
14089
- if (search) {
14090
- query.$text = { $search: search };
14091
- cacheOptions.search = search;
14092
- }
14093
- const cacheKey = (0, import_node_server_utils70.makeCacheKey)(vehicles_namespace_collection, cacheOptions);
14094
- const cachedData = await getCache(cacheKey);
14095
- if (cachedData) {
14096
- import_node_server_utils70.logger.info(`Cache hit for key: ${cacheKey}`);
14097
- return cachedData;
14098
- }
14012
+ let query = { ...baseQuery };
14099
14013
  const escapeRegex = (input) => input.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
14100
14014
  const buildGroupedPipeline = (matchQuery) => [
14101
14015
  { $match: matchQuery },
@@ -14253,9 +14167,6 @@ function useVehicleRepo() {
14253
14167
  length = regexCountResult[0]?.total || 0;
14254
14168
  }
14255
14169
  const data = (0, import_node_server_utils70.paginate)(items, page, limit, length);
14256
- setCache(cacheKey, data, 15 * 60).then(() => import_node_server_utils70.logger.info(`Cache set for key: ${cacheKey}`)).catch(
14257
- (err) => import_node_server_utils70.logger.error(`Failed to set cache for key: ${cacheKey}`, err)
14258
- );
14259
14170
  return data;
14260
14171
  } catch (error) {
14261
14172
  throw error;
@@ -14267,14 +14178,6 @@ function useVehicleRepo() {
14267
14178
  } catch (error) {
14268
14179
  throw new import_node_server_utils70.BadRequestError("Invalid site ID format.");
14269
14180
  }
14270
- const cacheKey = (0, import_node_server_utils70.makeCacheKey)(vehicles_namespace_collection, {
14271
- site,
14272
- type: "season-pass-type-as-options"
14273
- });
14274
- const cachedData = await getCache(cacheKey);
14275
- if (cachedData) {
14276
- return cachedData;
14277
- }
14278
14181
  try {
14279
14182
  const categories = await collection.aggregate([
14280
14183
  { $match: { site } },
@@ -14294,17 +14197,6 @@ function useVehicleRepo() {
14294
14197
  },
14295
14198
  { $sort: { title: 1 } }
14296
14199
  ]).toArray();
14297
- setCache(cacheKey, categories).then(() => {
14298
- import_node_server_utils70.logger.log({
14299
- level: "info",
14300
- message: `Cache set for get season pass type: ${cacheKey}`
14301
- });
14302
- }).catch((err) => {
14303
- import_node_server_utils70.logger.log({
14304
- level: "error",
14305
- message: `Failed to set cache for season pass type: ${err.message}`
14306
- });
14307
- });
14308
14200
  return categories;
14309
14201
  } catch (error) {
14310
14202
  if (error instanceof import_node_server_utils70.BadRequestError) {
@@ -14320,12 +14212,6 @@ function useVehicleRepo() {
14320
14212
  throw new import_node_server_utils70.BadRequestError("Invalid vehicle ID format.");
14321
14213
  }
14322
14214
  try {
14323
- const cacheKey = (0, import_node_server_utils70.makeCacheKey)(vehicles_namespace_collection, { _id });
14324
- const cachedData = await getCache(cacheKey);
14325
- if (cachedData) {
14326
- import_node_server_utils70.logger.info(`Cache hit for key: ${cacheKey}`);
14327
- return cachedData;
14328
- }
14329
14215
  const data = await collection.aggregate([
14330
14216
  { $match: { _id } },
14331
14217
  { $limit: 1 },
@@ -14495,11 +14381,6 @@ function useVehicleRepo() {
14495
14381
  throw new import_node_server_utils70.NotFoundError("Vehicle not found.");
14496
14382
  }
14497
14383
  const result = data[0];
14498
- setCache(cacheKey, result, 15 * 60).then(() => {
14499
- import_node_server_utils70.logger.info(`Cache set for key: ${cacheKey}`);
14500
- }).catch((err) => {
14501
- import_node_server_utils70.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
14502
- });
14503
14384
  return result;
14504
14385
  } catch (error) {
14505
14386
  throw error;
@@ -14511,15 +14392,6 @@ function useVehicleRepo() {
14511
14392
  throw new import_node_server_utils70.BadRequestError(error.details[0].message);
14512
14393
  }
14513
14394
  try {
14514
- const cacheKey = (0, import_node_server_utils70.makeCacheKey)(vehicles_namespace_collection, {
14515
- plateNumber: value,
14516
- status: "active"
14517
- });
14518
- const cachedData = await getCache(cacheKey);
14519
- if (cachedData) {
14520
- import_node_server_utils70.logger.info(`Cache hit for key: ${cacheKey}`);
14521
- return cachedData;
14522
- }
14523
14395
  const data = await collection.findOne({
14524
14396
  plateNumber: value,
14525
14397
  status: "active"
@@ -14527,11 +14399,6 @@ function useVehicleRepo() {
14527
14399
  if (!data) {
14528
14400
  throw new import_node_server_utils70.NotFoundError("Vehicle not found.");
14529
14401
  }
14530
- setCache(cacheKey, data, 15 * 60).then(() => {
14531
- import_node_server_utils70.logger.info(`Cache set for key: ${cacheKey}`);
14532
- }).catch((err) => {
14533
- import_node_server_utils70.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
14534
- });
14535
14402
  return data;
14536
14403
  } catch (error2) {
14537
14404
  throw error2;
@@ -14556,16 +14423,6 @@ function useVehicleRepo() {
14556
14423
  if (res.modifiedCount === 0) {
14557
14424
  throw new import_node_server_utils70.InternalServerError("Unable to update vehicle.");
14558
14425
  }
14559
- delNamespace().then(() => {
14560
- import_node_server_utils70.logger.info(
14561
- `Cache cleared for namespace: ${vehicles_namespace_collection}`
14562
- );
14563
- }).catch((err) => {
14564
- import_node_server_utils70.logger.error(
14565
- `Failed to clear cache for namespace: ${vehicles_namespace_collection}`,
14566
- err
14567
- );
14568
- });
14569
14426
  return res.modifiedCount;
14570
14427
  } catch (error) {
14571
14428
  throw error;
@@ -14589,16 +14446,6 @@ function useVehicleRepo() {
14589
14446
  );
14590
14447
  if (res.modifiedCount === 0)
14591
14448
  throw new import_node_server_utils70.InternalServerError("Unable to delete vehicle.");
14592
- delNamespace().then(() => {
14593
- import_node_server_utils70.logger.info(
14594
- `Cache cleared for namespace: ${vehicles_namespace_collection}`
14595
- );
14596
- }).catch((err) => {
14597
- import_node_server_utils70.logger.error(
14598
- `Failed to clear cache for namespace: ${vehicles_namespace_collection}`,
14599
- err
14600
- );
14601
- });
14602
14449
  return res.modifiedCount;
14603
14450
  } catch (error) {
14604
14451
  throw error;
@@ -14609,25 +14456,11 @@ function useVehicleRepo() {
14609
14456
  if (error) {
14610
14457
  throw new import_node_server_utils70.BadRequestError(error.details[0].message);
14611
14458
  }
14612
- const cacheKey = (0, import_node_server_utils70.makeCacheKey)(vehicles_namespace_collection, {
14613
- plateNumber,
14614
- status: "active"
14615
- });
14616
14459
  try {
14617
- const cacheData = await getCache(cacheKey);
14618
- if (cacheData) {
14619
- import_node_server_utils70.logger.info(`Cache hit for key: ${cacheKey}`);
14620
- return cacheData;
14621
- }
14622
14460
  const data = await collection.findOne(
14623
14461
  { plateNumber, status: "active" },
14624
14462
  { sort: { _id: -1 } }
14625
14463
  );
14626
- setCache(cacheKey, data, 15 * 60).then(() => {
14627
- import_node_server_utils70.logger.info(`Cache set for key: ${cacheKey}`);
14628
- }).catch((err) => {
14629
- import_node_server_utils70.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
14630
- });
14631
14464
  return data;
14632
14465
  } catch (error2) {
14633
14466
  throw new import_node_server_utils70.InternalServerError(
@@ -14651,19 +14484,6 @@ function useVehicleRepo() {
14651
14484
  nric: _nric
14652
14485
  };
14653
14486
  sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
14654
- const cacheOptions = {
14655
- deletedAt: "",
14656
- nric: _nric,
14657
- page: String(page),
14658
- limit: String(limit),
14659
- sort: JSON.stringify(sort)
14660
- };
14661
- const cacheKey = (0, import_node_server_utils70.makeCacheKey)(vehicles_namespace_collection, cacheOptions);
14662
- const cachedData = await getCache(cacheKey);
14663
- if (cachedData) {
14664
- import_node_server_utils70.logger.info(`Cache hit for key: ${cacheKey}`);
14665
- return cachedData;
14666
- }
14667
14487
  try {
14668
14488
  const items = await collection.aggregate([
14669
14489
  { $match: query },
@@ -14684,9 +14504,6 @@ function useVehicleRepo() {
14684
14504
  ]).toArray();
14685
14505
  const length = await collection.countDocuments(query);
14686
14506
  const data = (0, import_node_server_utils70.paginate)(items, page, limit, length);
14687
- setCache(cacheKey, data, 15 * 60).then(() => import_node_server_utils70.logger.info(`Cache set for key: ${cacheKey}`)).catch(
14688
- (err) => import_node_server_utils70.logger.error(`Failed to set cache for key: ${cacheKey}`, err)
14689
- );
14690
14507
  return data;
14691
14508
  } catch (error) {
14692
14509
  throw error;
@@ -14701,19 +14518,9 @@ function useVehicleRepo() {
14701
14518
  end: { $exists: true, $lte: now }
14702
14519
  // check only end
14703
14520
  },
14704
- { $set: { status: "deleted", deletedAt: now } },
14521
+ { $set: { status: "deleted", deletedAt: now, isDeletedInDahua: true } },
14705
14522
  { session }
14706
14523
  );
14707
- delNamespace().then(() => {
14708
- import_node_server_utils70.logger.info(
14709
- `Cache cleared for namespace: ${vehicles_namespace_collection}`
14710
- );
14711
- }).catch((err) => {
14712
- import_node_server_utils70.logger.error(
14713
- `Failed to clear cache for namespace: ${vehicles_namespace_collection}`,
14714
- err
14715
- );
14716
- });
14717
14524
  return res.modifiedCount;
14718
14525
  } catch (error) {
14719
14526
  throw error;
@@ -14732,21 +14539,6 @@ function useVehicleRepo() {
14732
14539
  const query = {
14733
14540
  unit
14734
14541
  };
14735
- const cacheOptions = {
14736
- unit: unitId,
14737
- page,
14738
- limit,
14739
- sort: JSON.stringify(sort)
14740
- };
14741
- const cacheKey = (0, import_node_server_utils70.makeCacheKey)(
14742
- vehicles_namespace_collection,
14743
- cacheOptions
14744
- );
14745
- const cachedData = await getCache(cacheKey);
14746
- if (cachedData) {
14747
- import_node_server_utils70.logger.info(`Cache hit for key: ${cacheKey}`);
14748
- return cachedData;
14749
- }
14750
14542
  const items = await collection.find(query, {
14751
14543
  projection: {
14752
14544
  createdAt: 0,
@@ -14759,14 +14551,24 @@ function useVehicleRepo() {
14759
14551
  }).toArray();
14760
14552
  const length = await collection.countDocuments(query);
14761
14553
  const data = (0, import_node_server_utils70.paginate)(items, page, limit, length);
14762
- setCache(cacheKey, data, 15 * 60).then(() => import_node_server_utils70.logger.info(`Cache set for key: ${cacheKey}`)).catch(
14763
- (err) => import_node_server_utils70.logger.error(`Failed to set cache for key: ${cacheKey}`, err)
14764
- );
14765
14554
  return data;
14766
14555
  } catch (error) {
14767
14556
  throw error;
14768
14557
  }
14769
14558
  }
14559
+ async function getAllExpiredVehicles() {
14560
+ try {
14561
+ const now = (/* @__PURE__ */ new Date()).toISOString();
14562
+ const query = {
14563
+ end: { $lte: now },
14564
+ status: { $ne: "deleted" }
14565
+ };
14566
+ const items = await collection.find(query).toArray();
14567
+ return items;
14568
+ } catch (error) {
14569
+ throw error;
14570
+ }
14571
+ }
14770
14572
  return {
14771
14573
  createIndex,
14772
14574
  createTextIndex,
@@ -14780,7 +14582,8 @@ function useVehicleRepo() {
14780
14582
  getVehicleByPlateNumber,
14781
14583
  getVehiclesByNRIC,
14782
14584
  deleteExpiredVehicles,
14783
- getAllVehiclesByUnitId
14585
+ getAllVehiclesByUnitId,
14586
+ getAllExpiredVehicles
14784
14587
  };
14785
14588
  }
14786
14589
 
@@ -15393,18 +15196,32 @@ function formatDahuaDate(date) {
15393
15196
  date.getSeconds()
15394
15197
  )}`;
15395
15198
  }
15199
+ function parseDahuaFind(text) {
15200
+ const found = Number(text.match(/found=(\d+)/)?.[1] || 0);
15201
+ if (!found) {
15202
+ return { exists: false };
15203
+ }
15204
+ return {
15205
+ exists: true,
15206
+ recNo: text.match(/records\[0\]\.RecNo=(.*)/)?.[1]?.trim(),
15207
+ plateNumber: text.match(/records\[0\]\.PlateNumber=(.*)/)?.[1]?.trim()
15208
+ };
15209
+ }
15396
15210
  function useVehicleService() {
15397
15211
  const {
15398
15212
  add: _add,
15399
15213
  deleteVehicle: _deleteVehicle,
15400
15214
  updateVehicleById: _updateVehicleById,
15401
15215
  getVehicleById: _getVehicleById,
15402
- deleteExpiredVehicles: _deleteExpiredVehicles
15216
+ deleteExpiredVehicles: _deleteExpiredVehicles,
15217
+ getVehicleByPlateNumber: _getVehicleByPlateNumber,
15218
+ getAllExpiredVehicles: _getAllExpiredVehicles
15403
15219
  } = useVehicleRepo();
15404
15220
  const {
15405
15221
  addPlateNumber: _addPlateNumber,
15406
15222
  removePlateNumber: _removePlateNumber,
15407
- updatePlateNumber: _updatePlateNumber
15223
+ updatePlateNumber: _updatePlateNumber,
15224
+ getPlateNumber: _getPlateNumber
15408
15225
  } = useDahuaService();
15409
15226
  const { getAllCameraWithPassword: _getAllSiteCameras } = useSiteCameraRepo();
15410
15227
  const { getById: _getById } = useOrgRepo();
@@ -15415,9 +15232,15 @@ function useVehicleService() {
15415
15232
  if (!session) {
15416
15233
  throw new Error("Unable to start session for vehicle service.");
15417
15234
  }
15418
- const org = await _getById(value.org);
15235
+ const [_vehiclePlateNumber] = value.plateNumber;
15236
+ const [existingPlateNumber, org] = await Promise.all([
15237
+ _getVehicleByPlateNumber(_vehiclePlateNumber),
15238
+ _getById(value.org)
15239
+ ]);
15419
15240
  if (!org)
15420
15241
  throw new import_node_server_utils72.BadRequestError("Org not found");
15242
+ if (existingPlateNumber)
15243
+ throw new import_node_server_utils72.BadRequestError("Vehicle plate number already exists");
15421
15244
  if (!Object.values(OrgNature).includes(org.nature)) {
15422
15245
  throw new import_node_server_utils72.BadRequestError(
15423
15246
  "This organization is not allowed to add vehicles."
@@ -15497,29 +15320,61 @@ function useVehicleService() {
15497
15320
  if (vehicleValue.status && vehicleValue.status !== "pending" /* PENDING */) {
15498
15321
  for (const camera of siteCameras) {
15499
15322
  const { host, username, password } = camera;
15500
- const dahuaPayload = {
15323
+ const plateNumber2 = vehicleValue.plateNumber;
15324
+ const dahuaQuery = {
15501
15325
  host,
15502
15326
  username,
15503
15327
  password,
15504
- plateNumber,
15505
- mode: _mode,
15506
- owner,
15507
- ...startDateDahua ? { start: startDateDahua } : {},
15508
- ...endDateDahua ? { end: endDateDahua } : {}
15328
+ plateNumber: plateNumber2,
15329
+ mode: _mode
15509
15330
  };
15510
- const dahuaResponse = await _addPlateNumber(dahuaPayload);
15511
- if (dahuaResponse?.statusCode !== 200) {
15512
- throw new import_node_server_utils72.BadRequestError(
15513
- `Failed to add plate number to ANPR ${_type}`
15514
- );
15331
+ const raw = await _getPlateNumber(dahuaQuery);
15332
+ const parsed = parseDahuaFind(raw);
15333
+ if (!parsed.exists) {
15334
+ const dahuaPayload = {
15335
+ host,
15336
+ username,
15337
+ password,
15338
+ plateNumber: plateNumber2,
15339
+ mode: _mode,
15340
+ owner,
15341
+ ...startDateDahua ? { start: startDateDahua } : {},
15342
+ ...endDateDahua ? { end: endDateDahua } : {}
15343
+ };
15344
+ const dahuaResponse = await _addPlateNumber(dahuaPayload);
15345
+ if (dahuaResponse?.statusCode !== 200) {
15346
+ throw new import_node_server_utils72.BadRequestError(
15347
+ `Failed to add plate number to ANPR ${_type}`
15348
+ );
15349
+ }
15350
+ const responseData = dahuaResponse?.data?.toString("utf-8") ?? "";
15351
+ vehicleValue.recNo = responseData.split("=")[1]?.trim();
15352
+ } else {
15353
+ const dahuaPayload = {
15354
+ host,
15355
+ username,
15356
+ password,
15357
+ plateNumber: plateNumber2,
15358
+ recno: parsed.recNo,
15359
+ mode: _mode,
15360
+ ...startDateDahua ? { start: startDateDahua } : {},
15361
+ ...endDateDahua ? { end: endDateDahua } : {},
15362
+ owner,
15363
+ isOpenGate: true
15364
+ };
15365
+ const dahuaResponse = await _updatePlateNumber(dahuaPayload);
15366
+ if (dahuaResponse?.statusCode !== 200) {
15367
+ throw new import_node_server_utils72.BadRequestError(
15368
+ `Failed to update plate number to ANPR ${_type}`
15369
+ );
15370
+ }
15371
+ vehicleValue.recNo = parsed.recNo;
15515
15372
  }
15516
- const responseData = dahuaResponse?.data?.toString("utf-8") ?? "";
15517
- vehicleValue.recNo = responseData.split("=")[1]?.trim();
15518
15373
  if (value.peopleId && vehicleValue.recNo) {
15519
15374
  await _pushVehicleById(
15520
15375
  value.peopleId,
15521
15376
  {
15522
- plateNumber,
15377
+ plateNumber: plateNumber2,
15523
15378
  recNo: vehicleValue.recNo
15524
15379
  },
15525
15380
  session
@@ -15710,6 +15565,43 @@ function useVehicleService() {
15710
15565
  }
15711
15566
  try {
15712
15567
  session.startTransaction();
15568
+ const vehicles = await _getAllExpiredVehicles();
15569
+ let siteCameras = [];
15570
+ for (const vehicle of vehicles) {
15571
+ const site = vehicle.site;
15572
+ const recno = vehicle.recNo;
15573
+ let page = 1;
15574
+ let pages = 1;
15575
+ const limit = 20;
15576
+ do {
15577
+ const siteCameraReq = await _getAllSiteCameras({
15578
+ site,
15579
+ type: "anpr",
15580
+ direction: ["both", "entry"],
15581
+ page,
15582
+ limit
15583
+ });
15584
+ pages = siteCameraReq.pages || 1;
15585
+ siteCameras.push(...siteCameraReq.items);
15586
+ page++;
15587
+ } while (page < pages);
15588
+ if (!siteCameras.length) {
15589
+ throw new import_node_server_utils72.BadRequestError("No site cameras found.");
15590
+ }
15591
+ for (const camera of siteCameras) {
15592
+ const host = camera.host;
15593
+ const username = camera.username;
15594
+ const password = camera.password;
15595
+ const dahuaPayload = {
15596
+ host,
15597
+ username,
15598
+ password,
15599
+ recno,
15600
+ mode: "TrafficRedList" /* TRAFFIC_REDLIST */
15601
+ };
15602
+ await _removePlateNumber(dahuaPayload);
15603
+ }
15604
+ }
15713
15605
  await _deleteExpiredVehicles();
15714
15606
  await session.commitTransaction();
15715
15607
  return `Expired Vehicle plate numbers deleted successfully.`;
@@ -16105,16 +15997,20 @@ function useDahuaService() {
16105
15997
  "resident" /* RESIDENT */,
16106
15998
  "tenant" /* TENANT */
16107
15999
  ];
16000
+ let startDate = vehicle?.start ? new Date(vehicle?.start) : /* @__PURE__ */ new Date();
16001
+ let endDate = vehicle?.end ? new Date(vehicle?.end) : new Date(startDate.getTime() + 60 * 60 * 1e3);
16108
16002
  if (vehicle && typeof vehicle.category === "string" && typesForAutoRegister.includes(vehicle.category)) {
16109
16003
  visitorTransaction.name = vehicle.name;
16110
16004
  visitorTransaction.nric = vehicle.nric;
16111
16005
  visitorTransaction.contact = vehicle.phoneNumber;
16112
16006
  visitorTransaction.block = Number(vehicle.block);
16113
16007
  visitorTransaction.level = vehicle.level;
16114
- visitorTransaction.unit = vehicle.unit;
16008
+ visitorTransaction.unit = vehicle.unit?.toString();
16115
16009
  visitorTransaction.unitName = vehicle.unitName;
16116
- visitorTransaction.type = vehicle.category;
16010
+ visitorTransaction.type = "resident" /* RESIDENT */;
16117
16011
  visitorTransaction.status = "registered" /* REGISTERED */;
16012
+ visitorTransaction.recNo = vehicle.recNo;
16013
+ visitorTransaction.expiredAt = vehicle.end;
16118
16014
  }
16119
16015
  const dahuaPayload = {
16120
16016
  host,
@@ -16124,13 +16020,15 @@ function useDahuaService() {
16124
16020
  mode: "TrafficRedList" /* TRAFFIC_REDLIST */,
16125
16021
  owner: vehicle?.name ?? ""
16126
16022
  };
16023
+ dahuaPayload.start = formatDahuaDate(startDate);
16024
+ dahuaPayload.end = formatDahuaDate(endDate);
16127
16025
  const shouldHaveTimeLimit = visitorTransaction.type === "guest" /* GUEST */ || visitorTransaction.status === "unregistered" /* UNREGISTERED */;
16128
16026
  if (shouldHaveTimeLimit) {
16129
- const startDate = /* @__PURE__ */ new Date();
16130
- const endDate = new Date(startDate.getTime() + 15 * 60 * 1e3);
16131
- dahuaPayload.start = formatDahuaDate(startDate);
16132
- dahuaPayload.end = formatDahuaDate(endDate);
16133
- visitorTransaction.expiredAt = endDate.toISOString();
16027
+ const startDate2 = /* @__PURE__ */ new Date();
16028
+ const endDate2 = new Date(startDate2.getTime() + 60 * 60 * 1e3);
16029
+ dahuaPayload.start = formatDahuaDate(startDate2);
16030
+ dahuaPayload.end = formatDahuaDate(endDate2);
16031
+ visitorTransaction.expiredAt = endDate2.toISOString();
16134
16032
  }
16135
16033
  try {
16136
16034
  await addPlateNumber(dahuaPayload);
@@ -16379,14 +16277,14 @@ function useDahuaService() {
16379
16277
  start: import_joi39.default.string().isoDate().optional().allow("", null),
16380
16278
  end: import_joi39.default.string().isoDate().optional().allow("", null),
16381
16279
  owner: import_joi39.default.string().optional().allow("", null),
16382
- openGate: import_joi39.default.boolean().optional().allow(null)
16280
+ isOpenGate: import_joi39.default.boolean().optional().allow(null)
16383
16281
  });
16384
16282
  const { error } = validation.validate(value);
16385
16283
  if (error) {
16386
16284
  throw new import_node_server_utils73.BadRequestError(`Validation error: ${error.message}`);
16387
16285
  }
16388
16286
  value.owner = String(value.owner ?? "").substring(0, 15) || "unknown";
16389
- const _openGate = String(value.openGate);
16287
+ const _openGate = String(value.isOpenGate);
16390
16288
  const isOpenGateString = _openGate && _openGate !== "undefined" ? _openGate : "true";
16391
16289
  const endpoint = `/cgi-bin/recordUpdater.cgi?action=insert&name=${value.mode}&PlateNumber=${value.plateNumber}&BeginTime=${value.start}&CancelTime=${value.end}&+OpenGate=${isOpenGateString}&MasterOfCar=${value.owner}`;
16392
16290
  try {
@@ -16447,7 +16345,7 @@ function useDahuaService() {
16447
16345
  username: import_joi39.default.string().required(),
16448
16346
  password: import_joi39.default.string().required(),
16449
16347
  recno: import_joi39.default.string().required(),
16450
- mode: import_joi39.default.string().valid("TrafficBlackList", "TrafficRedList").required()
16348
+ mode: import_joi39.default.string().valid(...Object.values(ANPRMode)).required()
16451
16349
  });
16452
16350
  const { error } = validation.validate(value);
16453
16351
  if (error) {
@@ -16465,12 +16363,39 @@ function useDahuaService() {
16465
16363
  import_node_server_utils73.logger.error(`[${value.host}] Error removing plate number:`, error2);
16466
16364
  }
16467
16365
  }
16366
+ async function getPlateNumber(value) {
16367
+ const validation = import_joi39.default.object({
16368
+ host: import_joi39.default.string().required(),
16369
+ username: import_joi39.default.string().required(),
16370
+ password: import_joi39.default.string().required(),
16371
+ plateNumber: import_joi39.default.string().required(),
16372
+ mode: import_joi39.default.string().valid(...Object.values(ANPRMode)).required()
16373
+ });
16374
+ const { error } = validation.validate(value);
16375
+ if (error) {
16376
+ throw new import_node_server_utils73.BadRequestError(`Validation error: ${error.message}`);
16377
+ }
16378
+ try {
16379
+ const response = await useDahuaDigest({
16380
+ host: value.host,
16381
+ username: value.username,
16382
+ password: value.password,
16383
+ endpoint: `/cgi-bin/recordFinder.cgi?action=find&name=${value.mode}&condition.PlateNumber=${encodeURIComponent(value.plateNumber)}`
16384
+ });
16385
+ const text = response?.data?.toString?.("utf-8");
16386
+ return text;
16387
+ } catch (error2) {
16388
+ import_node_server_utils73.logger.error(`[${value.host}] Error finding plate number:`, error2);
16389
+ throw error2;
16390
+ }
16391
+ }
16468
16392
  return {
16469
16393
  getSnapshot,
16470
16394
  getTrafficJunction,
16471
16395
  addPlateNumber,
16472
16396
  removePlateNumber,
16473
- updatePlateNumber
16397
+ updatePlateNumber,
16398
+ getPlateNumber
16474
16399
  };
16475
16400
  }
16476
16401
 
@@ -20726,10 +20651,13 @@ function useVisitorTransactionService() {
20726
20651
  const { getSiteById: _getSiteById } = useSiteRepo();
20727
20652
  const {
20728
20653
  addPlateNumber: _addPlateNumber,
20729
- removePlateNumber: _removePlateNumber
20654
+ removePlateNumber: _removePlateNumber,
20655
+ getPlateNumber: _getPlateNumber,
20656
+ updatePlateNumber: _updatePlateNumber
20730
20657
  } = useDahuaService();
20731
20658
  const { getAllSites: _getAllSites } = useSiteRepo();
20732
20659
  const { getByUserId: _getByUserId } = usePersonRepo();
20660
+ const { add: addVehicle } = useVehicleRepo();
20733
20661
  async function add(value) {
20734
20662
  const session = import_node_server_utils100.useAtlas.getClient()?.startSession();
20735
20663
  const allowedPersonTypes = [
@@ -20746,12 +20674,12 @@ function useVisitorTransactionService() {
20746
20674
  let site;
20747
20675
  if (value.site) {
20748
20676
  [camera, site] = await Promise.all([
20749
- _getBySite(value.site, { type: "anpr" }),
20677
+ _getBySite(value.site, { type: "anpr" /* ANPR */ }),
20750
20678
  _getSiteById(value.site)
20751
20679
  ]);
20752
20680
  }
20753
- const minutesExpiration = site?.dahuaTimeExpiration ? site?.dahuaTimeExpiration : 60;
20754
- const end = value.checkOut ? new Date(value.checkOut) : new Date(start.getTime() + minutesExpiration * 60 * 1e3);
20681
+ const hourExpiration = site?.dahuaTimeExpiration ? site?.dahuaTimeExpiration : 24 * 60;
20682
+ const end = value.checkOut ? new Date(value.checkOut) : new Date(start.getTime() + hourExpiration * 60 * 1e3);
20755
20683
  const startString = start.toISOString();
20756
20684
  const endString = end.toISOString();
20757
20685
  const startDahuaDate = formatDahuaDate(start);
@@ -20827,27 +20755,76 @@ function useVisitorTransactionService() {
20827
20755
  }
20828
20756
  }
20829
20757
  if (camera && value.plateNumber && camera.host && camera.username && camera.password) {
20830
- const dahuaPayload = {
20831
- host: camera.host,
20832
- username: camera.username,
20833
- password: camera.password,
20834
- plateNumber: value.plateNumber,
20835
- mode: "TrafficRedList" /* TRAFFIC_REDLIST */,
20836
- start: startDahuaDate,
20837
- end: endDahuaDate,
20838
- owner: value.name ?? "",
20839
- openGate: site?.isOpenGate ?? true
20758
+ const host = camera.host;
20759
+ const username = camera.username;
20760
+ const password = camera.password;
20761
+ const mode = "TrafficRedList" /* TRAFFIC_REDLIST */;
20762
+ const _plateNumber = value.plateNumber;
20763
+ const dahuaQuery = {
20764
+ host,
20765
+ username,
20766
+ password,
20767
+ plateNumber: _plateNumber,
20768
+ mode
20840
20769
  };
20841
- const dahuaResponse = await _addPlateNumber(dahuaPayload);
20842
- if (dahuaResponse?.statusCode !== 200) {
20843
- throw new import_node_server_utils100.BadRequestError(
20844
- `Failed to add plate number to ANPR whitelist`
20845
- );
20770
+ const raw = await _getPlateNumber(dahuaQuery);
20771
+ const parsed = parseDahuaFind(raw);
20772
+ if (!parsed.exists) {
20773
+ const dahuaPayload = {
20774
+ host,
20775
+ username,
20776
+ password,
20777
+ plateNumber: _plateNumber,
20778
+ mode,
20779
+ start: startDahuaDate,
20780
+ end: endDahuaDate,
20781
+ owner: value.name ?? "",
20782
+ isOpenGate: site?.isOpenGate ?? true
20783
+ };
20784
+ const dahuaResponse = await _addPlateNumber(dahuaPayload);
20785
+ if (dahuaResponse?.statusCode !== 200) {
20786
+ throw new import_node_server_utils100.BadRequestError(
20787
+ `Failed to add plate number to ANPR whitelist`
20788
+ );
20789
+ }
20790
+ const responseData = dahuaResponse?.data?.toString("utf-8") ?? "";
20791
+ value.recNo = responseData.split("=")[1]?.trim();
20792
+ value.checkIn = startString;
20793
+ value.expiredAt = endString;
20794
+ const vehiclePayload = {
20795
+ name: value.name ?? "",
20796
+ category: value.type,
20797
+ org: value.org,
20798
+ site: value.site,
20799
+ plateNumber: value.plateNumber,
20800
+ type: "whitelist" /* WHITELIST */,
20801
+ nric: value.nric,
20802
+ start: startString,
20803
+ end: endString,
20804
+ recNo: value.recNo
20805
+ };
20806
+ await addVehicle(vehiclePayload);
20807
+ } else {
20808
+ const dahuaPayload = {
20809
+ host,
20810
+ username,
20811
+ password,
20812
+ plateNumber: _plateNumber,
20813
+ recno: parsed.recNo,
20814
+ mode,
20815
+ start: startDahuaDate,
20816
+ end: endDahuaDate,
20817
+ owner: value.name ?? "",
20818
+ isOpenGate: site?.isOpenGate ?? true
20819
+ };
20820
+ const dahuaResponse = await _updatePlateNumber(dahuaPayload);
20821
+ if (dahuaResponse?.statusCode !== 200) {
20822
+ throw new import_node_server_utils100.BadRequestError(
20823
+ `Failed to update plate number to ANPR ${"whitelist" /* WHITELIST */}`
20824
+ );
20825
+ }
20826
+ value.recNo = parsed.recNo;
20846
20827
  }
20847
- const responseData = dahuaResponse?.data?.toString("utf-8") ?? "";
20848
- value.recNo = responseData.split("=")[1]?.trim();
20849
- value.checkIn = startString;
20850
- value.expiredAt = endString;
20851
20828
  }
20852
20829
  const result = await _add(value, session);
20853
20830
  await session?.commitTransaction();
@@ -21181,7 +21158,6 @@ function useVisitorTransactionController() {
21181
21158
  }
21182
21159
  }
21183
21160
  async function inviteVisitor(req, res, next) {
21184
- const inviter = req.params.inviterId;
21185
21161
  const schema2 = import_joi55.default.object({
21186
21162
  name: import_joi55.default.string().required(),
21187
21163
  contact: import_joi55.default.string().required(),
@@ -45248,12 +45224,6 @@ function useVerificationRepoV2() {
45248
45224
  err
45249
45225
  );
45250
45226
  });
45251
- const cacheKey = (0, import_node_server_utils217.makeCacheKey)(namespace_collection, { _id });
45252
- delCache(cacheKey).then(() => {
45253
- import_node_server_utils217.logger.info(`Cache deleted for key: ${cacheKey}`);
45254
- }).catch((err) => {
45255
- import_node_server_utils217.logger.error(`Failed to delete cache for key: ${cacheKey}`, err);
45256
- });
45257
45227
  return result;
45258
45228
  } catch (error) {
45259
45229
  throw new import_node_server_utils217.InternalServerError("Error updating verification status.");
@@ -45659,9 +45629,12 @@ function useVerificationControllerV2() {
45659
45629
  async function verify(req, res, next) {
45660
45630
  try {
45661
45631
  const schema2 = import_joi126.default.object({ verificationCode: import_joi126.default.string().required() });
45662
- const { error, value } = schema2.validate({
45663
- verificationCode: req.params.verificationCode
45664
- });
45632
+ const { error, value } = schema2.validate(
45633
+ {
45634
+ verificationCode: req.params.verificationCode
45635
+ },
45636
+ { abortEarly: false }
45637
+ );
45665
45638
  if (error) {
45666
45639
  const messages = error.details.map((d) => d.message).join(", ");
45667
45640
  import_node_server_utils219.logger.log({ level: "error", message: messages });
@@ -45687,7 +45660,7 @@ function useVerificationControllerV2() {
45687
45660
  siteId: import_joi126.default.string().hex().length(24).optional().allow("", null),
45688
45661
  siteName: import_joi126.default.string().optional().allow("", null)
45689
45662
  });
45690
- const { error, value } = schema2.validate(req.body);
45663
+ const { error, value } = schema2.validate(req.body, { abortEarly: false });
45691
45664
  if (error) {
45692
45665
  const messages = error.details.map((d) => d.message).join(", ");
45693
45666
  import_node_server_utils219.logger.log({ level: "error", message: messages });
@@ -45722,7 +45695,7 @@ function useVerificationControllerV2() {
45722
45695
  siteId: import_joi126.default.string().hex().length(24).required(),
45723
45696
  siteName: import_joi126.default.string().required()
45724
45697
  });
45725
- const { error, value } = schema2.validate(req.body);
45698
+ const { error, value } = schema2.validate(req.body, { abortEarly: false });
45726
45699
  if (error) {
45727
45700
  const messages = error.details.map((d) => d.message).join(", ");
45728
45701
  import_node_server_utils219.logger.log({ level: "error", message: messages });
@@ -45748,7 +45721,7 @@ function useVerificationControllerV2() {
45748
45721
  const schema2 = import_joi126.default.object({
45749
45722
  email: import_joi126.default.string().email().lowercase().required()
45750
45723
  });
45751
- const { error, value } = schema2.validate(req.body);
45724
+ const { error, value } = schema2.validate(req.body, { abortEarly: false });
45752
45725
  if (error) {
45753
45726
  const messages = error.details.map((d) => d.message).join(", ");
45754
45727
  import_node_server_utils219.logger.log({ level: "error", message: messages });
@@ -45778,13 +45751,14 @@ function useVerificationControllerV2() {
45778
45751
 
45779
45752
  // src/controllers/auth-v2.controller.ts
45780
45753
  var import_joi127 = __toESM(require("joi"));
45781
- var import_node_server_utils222 = require("@7365admin1/node-server-utils");
45754
+ var import_node_server_utils223 = require("@7365admin1/node-server-utils");
45782
45755
 
45783
45756
  // src/services/auth-v2.service.ts
45784
45757
  var import_node_server_utils221 = require("@7365admin1/node-server-utils");
45785
45758
  var import_uuid2 = require("uuid");
45786
45759
 
45787
45760
  // src/repositories/user-v2.repo.ts
45761
+ var import_mongodb123 = require("mongodb");
45788
45762
  var import_node_server_utils220 = require("@7365admin1/node-server-utils");
45789
45763
  function useUserRepoV2() {
45790
45764
  const { updateFeedbackCreatedByName } = useFeedbackRepo();
@@ -45796,6 +45770,7 @@ function useUserRepoV2() {
45796
45770
  }
45797
45771
  const namespace_collection = "users";
45798
45772
  const collection = db.collection(namespace_collection);
45773
+ const { delNamespace, setCache, getCache, delCache } = (0, import_node_server_utils220.useCache)(namespace_collection);
45799
45774
  async function createIndex() {
45800
45775
  try {
45801
45776
  await collection.createIndexes([{ key: { email: 1 } }]);
@@ -45805,10 +45780,7 @@ function useUserRepoV2() {
45805
45780
  }
45806
45781
  async function createTextIndex() {
45807
45782
  try {
45808
- await collection.createIndex({
45809
- name: "text",
45810
- email: "text"
45811
- });
45783
+ await collection.createIndex({ name: "text", email: "text" });
45812
45784
  } catch (error) {
45813
45785
  throw new import_node_server_utils220.InternalServerError("Failed to create text index on user.");
45814
45786
  }
@@ -45823,24 +45795,22 @@ function useUserRepoV2() {
45823
45795
  throw new import_node_server_utils220.InternalServerError("Failed to create unique index on user.");
45824
45796
  }
45825
45797
  }
45826
- const { delNamespace, setCache, getCache, delCache } = (0, import_node_server_utils220.useCache)(namespace_collection);
45827
45798
  async function createUser(value, session) {
45828
45799
  try {
45829
45800
  value = MUser(value);
45830
45801
  const res = await collection.insertOne(value, { session });
45831
- delNamespace().then(() => {
45832
- import_node_server_utils220.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
45833
- }).catch((err) => {
45834
- import_node_server_utils220.logger.error(
45802
+ delNamespace().then(
45803
+ () => import_node_server_utils220.logger.info(`Cache cleared for namespace: ${namespace_collection}`)
45804
+ ).catch(
45805
+ (err) => import_node_server_utils220.logger.error(
45835
45806
  `Failed to clear cache for namespace: ${namespace_collection}`,
45836
45807
  err
45837
- );
45838
- });
45808
+ )
45809
+ );
45839
45810
  return res.insertedId;
45840
45811
  } catch (error) {
45841
45812
  import_node_server_utils220.logger.log({ level: "error", message: `${error}` });
45842
- const isDuplicated = error.message.includes("duplicate");
45843
- if (isDuplicated) {
45813
+ if (error.message.includes("duplicate")) {
45844
45814
  throw new import_node_server_utils220.BadRequestError("User already exists.");
45845
45815
  }
45846
45816
  throw error;
@@ -45857,11 +45827,9 @@ function useUserRepoV2() {
45857
45827
  const data = await collection.findOne({
45858
45828
  email: { $regex: `^${email}$`, $options: "i" }
45859
45829
  });
45860
- setCache(cacheKey, data, 15 * 60).then(() => {
45861
- import_node_server_utils220.logger.info(`Cache set for key: ${cacheKey}`);
45862
- }).catch((err) => {
45863
- import_node_server_utils220.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
45864
- });
45830
+ setCache(cacheKey, data, 15 * 60).then(() => import_node_server_utils220.logger.info(`Cache set for key: ${cacheKey}`)).catch(
45831
+ (err) => import_node_server_utils220.logger.error(`Failed to set cache for key: ${cacheKey}`, err)
45832
+ );
45865
45833
  return data;
45866
45834
  } catch (error) {
45867
45835
  throw new import_node_server_utils220.InternalServerError("Failed to get user by email.");
@@ -45869,26 +45837,22 @@ function useUserRepoV2() {
45869
45837
  }
45870
45838
  async function getUserByEmailStatus(email) {
45871
45839
  try {
45872
- const cacheOptions = {
45840
+ const cacheKey = (0, import_node_server_utils220.makeCacheKey)(namespace_collection, {
45873
45841
  email,
45874
45842
  status: "complete" /* COMPLETE */
45875
- };
45876
- const cacheKey = (0, import_node_server_utils220.makeCacheKey)(namespace_collection, cacheOptions);
45843
+ });
45877
45844
  const cachedData = await getCache(cacheKey);
45878
45845
  if (cachedData) {
45879
45846
  import_node_server_utils220.logger.info(`Cache hit for key: ${cacheKey}`);
45880
45847
  return cachedData;
45881
45848
  }
45882
- const query = {
45849
+ const data = await collection.findOne({
45883
45850
  email: { $regex: `^${email}$`, $options: "i" },
45884
45851
  status: "complete" /* COMPLETE */
45885
- };
45886
- const data = await collection.findOne(query);
45887
- setCache(cacheKey, data, 15 * 60).then(() => {
45888
- import_node_server_utils220.logger.info(`Cache set for key: ${cacheKey}`);
45889
- }).catch((err) => {
45890
- import_node_server_utils220.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
45891
45852
  });
45853
+ setCache(cacheKey, data, 15 * 60).then(() => import_node_server_utils220.logger.info(`Cache set for key: ${cacheKey}`)).catch(
45854
+ (err) => import_node_server_utils220.logger.error(`Failed to set cache for key: ${cacheKey}`, err)
45855
+ );
45892
45856
  return data;
45893
45857
  } catch (error) {
45894
45858
  throw new import_node_server_utils220.InternalServerError("Failed to get user by email.");
@@ -45911,17 +45875,10 @@ function useUserRepoV2() {
45911
45875
  let: { userOrgId: "$defaultOrg" },
45912
45876
  pipeline: [
45913
45877
  {
45914
- $match: {
45915
- $expr: { $eq: ["$orgId", "$$userOrgId"] }
45916
- }
45878
+ $match: { $expr: { $eq: ["$orgId", "$$userOrgId"] } }
45917
45879
  },
45918
45880
  {
45919
- $project: {
45920
- _id: 1,
45921
- name: 1,
45922
- type: 1,
45923
- siteId: 1
45924
- }
45881
+ $project: { _id: 1, name: 1, type: 1, siteId: 1 }
45925
45882
  }
45926
45883
  ],
45927
45884
  as: "serviceProviders"
@@ -45929,9 +45886,117 @@ function useUserRepoV2() {
45929
45886
  }
45930
45887
  ]).toArray();
45931
45888
  const data = results.length > 0 ? results[0] : null;
45932
- if (!data) {
45889
+ if (!data)
45933
45890
  throw new import_node_server_utils220.NotFoundError("User not found.");
45891
+ setCache(cacheKey, data, 15 * 60).then(() => import_node_server_utils220.logger.info(`Cache set for key: ${cacheKey}`)).catch(
45892
+ (err) => import_node_server_utils220.logger.error(`Failed to set cache for key: ${cacheKey}`, err)
45893
+ );
45894
+ return data;
45895
+ } catch (error) {
45896
+ if (error instanceof import_node_server_utils220.AppError)
45897
+ throw error;
45898
+ throw new import_node_server_utils220.InternalServerError("Failed to get user by id.");
45899
+ }
45900
+ }
45901
+ async function getUserByReferralCode(referralCode) {
45902
+ try {
45903
+ const cacheKey = (0, import_node_server_utils220.makeCacheKey)(namespace_collection, { referralCode });
45904
+ const cachedData = await getCache(cacheKey);
45905
+ if (cachedData) {
45906
+ import_node_server_utils220.logger.info(`Cache hit for key: ${cacheKey}`);
45907
+ return cachedData;
45908
+ }
45909
+ const data = await collection.findOne({ referralCode });
45910
+ setCache(cacheKey, data, 15 * 60).then(() => import_node_server_utils220.logger.info(`Cache set for key: ${cacheKey}`)).catch(
45911
+ (err) => import_node_server_utils220.logger.error(`Failed to set cache for key: ${cacheKey}`, err)
45912
+ );
45913
+ return data;
45914
+ } catch (error) {
45915
+ throw new import_node_server_utils220.InternalServerError("Failed to get user by referral code.");
45916
+ }
45917
+ }
45918
+ async function getByEmailApp(email, app) {
45919
+ try {
45920
+ const cacheKey = (0, import_node_server_utils220.makeCacheKey)(namespace_collection, { email, app });
45921
+ const cachedData = await getCache(cacheKey);
45922
+ if (cachedData) {
45923
+ import_node_server_utils220.logger.info(`Cache hit for key: ${cacheKey}`);
45924
+ return cachedData;
45934
45925
  }
45926
+ const data = await collection.findOne({
45927
+ email,
45928
+ "roles.app": app
45929
+ });
45930
+ setCache(cacheKey, data, 15 * 60).then(() => import_node_server_utils220.logger.info(`Cache set for key: ${cacheKey}`)).catch(
45931
+ (err) => import_node_server_utils220.logger.error(`Failed to set cache for key: ${cacheKey}`, err)
45932
+ );
45933
+ return data;
45934
+ } catch (error) {
45935
+ throw new import_node_server_utils220.InternalServerError("Failed to get user by email and app.");
45936
+ }
45937
+ }
45938
+ async function getUsersByOrgId({
45939
+ organization = "",
45940
+ search = "",
45941
+ page = 1,
45942
+ limit = 10,
45943
+ sort = {},
45944
+ type = "",
45945
+ status = "active"
45946
+ }) {
45947
+ page = page > 0 ? page - 1 : 0;
45948
+ const query = { status };
45949
+ const cacheOptions = { status };
45950
+ sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
45951
+ cacheOptions.sort = JSON.stringify(sort);
45952
+ if (search) {
45953
+ query.$text = { $search: search };
45954
+ cacheOptions.search = search;
45955
+ }
45956
+ if (type) {
45957
+ query.type = type;
45958
+ cacheOptions.type = type;
45959
+ }
45960
+ if (organization) {
45961
+ try {
45962
+ query.defaultOrg = new import_mongodb123.ObjectId(organization);
45963
+ cacheOptions.organization = organization.toString();
45964
+ } catch (error) {
45965
+ throw new import_node_server_utils220.BadRequestError("Invalid organization ID format.");
45966
+ }
45967
+ }
45968
+ delNamespace().then(() => {
45969
+ import_node_server_utils220.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
45970
+ }).catch((err) => {
45971
+ import_node_server_utils220.logger.error(
45972
+ `Failed to clear cache for namespace: ${namespace_collection}`,
45973
+ err
45974
+ );
45975
+ });
45976
+ const cacheKey = (0, import_node_server_utils220.makeCacheKey)(namespace_collection, cacheOptions);
45977
+ const cachedData = await getCache(cacheKey);
45978
+ if (cachedData) {
45979
+ import_node_server_utils220.logger.info(`Cache hit for key: ${cacheKey}`);
45980
+ return cachedData;
45981
+ }
45982
+ try {
45983
+ const items = await collection.aggregate([
45984
+ { $match: query },
45985
+ { $sort: sort },
45986
+ { $skip: page * limit },
45987
+ { $limit: limit },
45988
+ {
45989
+ $project: {
45990
+ _id: 1,
45991
+ name: 1,
45992
+ email: 1,
45993
+ type: 1,
45994
+ status: 1
45995
+ }
45996
+ }
45997
+ ]).toArray();
45998
+ const length = await collection.countDocuments(query);
45999
+ const data = (0, import_node_server_utils220.paginate)(items, page, limit, length);
45935
46000
  setCache(cacheKey, data, 15 * 60).then(() => {
45936
46001
  import_node_server_utils220.logger.info(`Cache set for key: ${cacheKey}`);
45937
46002
  }).catch((err) => {
@@ -45939,12 +46004,197 @@ function useUserRepoV2() {
45939
46004
  });
45940
46005
  return data;
45941
46006
  } catch (error) {
45942
- if (error instanceof import_node_server_utils220.AppError) {
46007
+ import_node_server_utils220.logger.log({ level: "error", message: `${error}` });
46008
+ throw error;
46009
+ }
46010
+ }
46011
+ async function getUsers({
46012
+ search = "",
46013
+ page = 1,
46014
+ limit = 10,
46015
+ sort = {},
46016
+ type = "",
46017
+ status = "active"
46018
+ }) {
46019
+ page = page > 0 ? page - 1 : 0;
46020
+ const query = { status };
46021
+ const cacheOptions = { status };
46022
+ sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
46023
+ cacheOptions.sort = JSON.stringify(sort);
46024
+ if (search) {
46025
+ query.$text = { $search: search };
46026
+ cacheOptions.search = search;
46027
+ }
46028
+ if (type) {
46029
+ query.type = type;
46030
+ cacheOptions.type = type;
46031
+ }
46032
+ delNamespace().then(
46033
+ () => import_node_server_utils220.logger.info(`Cache cleared for namespace: ${namespace_collection}`)
46034
+ ).catch(
46035
+ (err) => import_node_server_utils220.logger.error(
46036
+ `Failed to clear cache for namespace: ${namespace_collection}`,
46037
+ err
46038
+ )
46039
+ );
46040
+ const cacheKey = (0, import_node_server_utils220.makeCacheKey)(namespace_collection, cacheOptions);
46041
+ const cachedData = await getCache(cacheKey);
46042
+ if (cachedData) {
46043
+ import_node_server_utils220.logger.info(`Cache hit for key: ${cacheKey}`);
46044
+ return cachedData;
46045
+ }
46046
+ try {
46047
+ const items = await collection.aggregate([
46048
+ { $match: query },
46049
+ { $sort: sort },
46050
+ { $skip: page * limit },
46051
+ { $limit: limit },
46052
+ { $project: { _id: 1, name: 1, email: 1, type: 1, status: 1 } }
46053
+ ]).toArray();
46054
+ const length = await collection.countDocuments(query);
46055
+ const data = (0, import_node_server_utils220.paginate)(items, page, limit, length);
46056
+ setCache(cacheKey, data, 15 * 60).then(() => import_node_server_utils220.logger.info(`Cache set for key: ${cacheKey}`)).catch(
46057
+ (err) => import_node_server_utils220.logger.error(`Failed to set cache for key: ${cacheKey}`, err)
46058
+ );
46059
+ return data;
46060
+ } catch (error) {
46061
+ import_node_server_utils220.logger.log({ level: "error", message: `${error}` });
46062
+ throw error;
46063
+ }
46064
+ }
46065
+ async function updatePasswordById({ _id, password }, session) {
46066
+ const cacheKey = (0, import_node_server_utils220.makeCacheKey)(namespace_collection, { _id });
46067
+ _id = (0, import_node_server_utils220.toObjectId)(_id);
46068
+ try {
46069
+ const result = await collection.updateOne(
46070
+ { _id },
46071
+ { $set: { password, updatedAt: (/* @__PURE__ */ new Date()).toISOString() } },
46072
+ { session }
46073
+ );
46074
+ delCache(cacheKey).then(() => {
46075
+ import_node_server_utils220.logger.info(`Cache deleted for key: ${cacheKey}`);
46076
+ }).catch((err) => {
46077
+ import_node_server_utils220.logger.error(`Failed to delete cache for key: ${cacheKey}`, err);
46078
+ });
46079
+ return result;
46080
+ } catch (error) {
46081
+ throw new import_node_server_utils220.InternalServerError("Failed to update user password.");
46082
+ }
46083
+ }
46084
+ async function updateUserFieldById({ _id, field, value } = {}, session) {
46085
+ const allowedFields = [
46086
+ "name",
46087
+ "email",
46088
+ "contact",
46089
+ "nric",
46090
+ "dateOfBirth",
46091
+ "profile",
46092
+ "gender",
46093
+ "defaultOrg"
46094
+ ];
46095
+ if (!allowedFields.includes(field)) {
46096
+ throw new import_node_server_utils220.BadRequestError(
46097
+ `Field "${field}" is not allowed to be updated.`
46098
+ );
46099
+ }
46100
+ try {
46101
+ _id = new import_mongodb123.ObjectId(_id);
46102
+ } catch (error) {
46103
+ throw new import_node_server_utils220.BadRequestError("Invalid ID.");
46104
+ }
46105
+ if (field === "defaultOrg") {
46106
+ try {
46107
+ value = new import_mongodb123.ObjectId(value);
46108
+ } catch (error) {
46109
+ throw new import_node_server_utils220.BadRequestError("Invalid organization ID.");
46110
+ }
46111
+ }
46112
+ if (field === "name") {
46113
+ try {
46114
+ await Promise.all([
46115
+ updateFeedbackCreatedByName(_id, value, session),
46116
+ updateWorkOrderCreatedByName(_id, value, session),
46117
+ updateUserNameBySignatureId(_id, value, session)
46118
+ ]);
46119
+ } catch (error) {
45943
46120
  throw error;
45944
- } else {
45945
- throw new import_node_server_utils220.InternalServerError("Failed to get user by email.");
45946
46121
  }
45947
46122
  }
46123
+ try {
46124
+ await collection.updateOne(
46125
+ { _id },
46126
+ { $set: { [field]: value, updatedAt: (/* @__PURE__ */ new Date()).toISOString() } },
46127
+ // Dynamically set the field
46128
+ { session }
46129
+ );
46130
+ const cacheKey = (0, import_node_server_utils220.makeCacheKey)(namespace_collection, { _id });
46131
+ delCache(cacheKey).then(() => {
46132
+ import_node_server_utils220.logger.info(`Cache deleted for key: ${cacheKey}`);
46133
+ }).catch((err) => {
46134
+ import_node_server_utils220.logger.error(`Failed to delete cache for key: ${cacheKey}`, err);
46135
+ });
46136
+ return `Successfully updated user ${field}.`;
46137
+ } catch (error) {
46138
+ throw new import_node_server_utils220.InternalServerError(`Failed to update user ${field}.`);
46139
+ }
46140
+ }
46141
+ async function updateBirthday({
46142
+ _id,
46143
+ month,
46144
+ day,
46145
+ year
46146
+ }, session) {
46147
+ try {
46148
+ _id = new import_mongodb123.ObjectId(_id);
46149
+ } catch (error) {
46150
+ throw new import_node_server_utils220.BadRequestError("Invalid user ID format.");
46151
+ }
46152
+ try {
46153
+ await collection.updateOne(
46154
+ { _id },
46155
+ {
46156
+ $set: {
46157
+ birthMonth: month,
46158
+ birthDay: day,
46159
+ birthYear: year,
46160
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
46161
+ }
46162
+ },
46163
+ { session }
46164
+ );
46165
+ const cacheKey = (0, import_node_server_utils220.makeCacheKey)(namespace_collection, { _id });
46166
+ delCache(cacheKey).then(() => {
46167
+ import_node_server_utils220.logger.info(`Cache deleted for key: ${cacheKey}`);
46168
+ }).catch((err) => {
46169
+ import_node_server_utils220.logger.error(`Failed to delete cache for key: ${cacheKey}`, err);
46170
+ });
46171
+ return "Successfully updated user birthday.";
46172
+ } catch (error) {
46173
+ throw new import_node_server_utils220.InternalServerError("Failed to update user birthday.");
46174
+ }
46175
+ }
46176
+ async function updatePassword({ _id, password }, session) {
46177
+ try {
46178
+ _id = new import_mongodb123.ObjectId(_id);
46179
+ } catch (error) {
46180
+ throw new import_node_server_utils220.BadRequestError("Invalid user ID format.");
46181
+ }
46182
+ try {
46183
+ const result = await collection.updateOne(
46184
+ { _id },
46185
+ { $set: { password, updatedAt: (/* @__PURE__ */ new Date()).toISOString() } },
46186
+ { session }
46187
+ );
46188
+ const cacheKey = (0, import_node_server_utils220.makeCacheKey)(namespace_collection, { _id });
46189
+ delCache(cacheKey).then(() => {
46190
+ import_node_server_utils220.logger.info(`Cache deleted for key: ${cacheKey}`);
46191
+ }).catch((err) => {
46192
+ import_node_server_utils220.logger.error(`Failed to delete cache for key: ${cacheKey}`, err);
46193
+ });
46194
+ return result;
46195
+ } catch (error) {
46196
+ throw new import_node_server_utils220.InternalServerError("Failed to update user password.");
46197
+ }
45948
46198
  }
45949
46199
  return {
45950
46200
  createIndex,
@@ -45953,7 +46203,13 @@ function useUserRepoV2() {
45953
46203
  createUser,
45954
46204
  getUserByEmail,
45955
46205
  getUserByEmailStatus,
45956
- getUserById
46206
+ getUserById,
46207
+ getUsers,
46208
+ getUsersByOrgId,
46209
+ updatePasswordById,
46210
+ updateUserFieldById,
46211
+ updateBirthday,
46212
+ updatePassword
45957
46213
  };
45958
46214
  }
45959
46215
 
@@ -46020,10 +46276,212 @@ function useAuthServiceV2() {
46020
46276
  };
46021
46277
  }
46022
46278
 
46279
+ // src/services/user-v2.service.ts
46280
+ var import_node_server_utils222 = require("@7365admin1/node-server-utils");
46281
+ var import_multer2 = require("multer");
46282
+ function useUserServiceV2() {
46283
+ const {
46284
+ createUser: _createUser,
46285
+ getUserByEmail: _getUserByEmail,
46286
+ updatePasswordById: _updatePasswordById,
46287
+ updateUserFieldById: _updateUserFieldById,
46288
+ getUserById,
46289
+ updatePassword
46290
+ } = useUserRepoV2();
46291
+ const { getRoleByName, addRole } = useRoleRepo();
46292
+ const { add: addMember } = useMemberRepo();
46293
+ const { getById: getOrgById } = useOrgRepo();
46294
+ const { getSiteById } = useSiteRepo();
46295
+ const {
46296
+ getVerificationById: _getVerificationById,
46297
+ updateVerificationStatusById: _updateVerificationStatusById
46298
+ } = useVerificationRepoV2();
46299
+ const { verify: _verify } = useVerificationServiceV2();
46300
+ const { createFile, deleteFileById } = useFileRepo();
46301
+ async function createUserBySignUp({
46302
+ id = "",
46303
+ name = ""
46304
+ }) {
46305
+ const session = import_node_server_utils222.useAtlas.getClient()?.startSession();
46306
+ session?.startTransaction();
46307
+ try {
46308
+ const signUp = await _getVerificationById(id);
46309
+ if (!signUp)
46310
+ throw new import_node_server_utils222.BadRequestError("Invalid sign up link.");
46311
+ if (signUp.status === "complete" /* COMPLETE */)
46312
+ throw new import_node_server_utils222.BadRequestError(
46313
+ "You have already an account created using this link."
46314
+ );
46315
+ const expired = signUp.expireAt < (/* @__PURE__ */ new Date()).toISOString();
46316
+ if (signUp.status === "expired" || expired)
46317
+ throw new import_node_server_utils222.BadRequestError("Sign up link expired.");
46318
+ const email = signUp.email;
46319
+ const _user = await _getUserByEmail(email);
46320
+ if (_user)
46321
+ throw new import_node_server_utils222.BadRequestError(`User already exists: ${email}.`);
46322
+ let org = null;
46323
+ if (signUp.metadata?.org) {
46324
+ org = await getOrgById(signUp.metadata.org);
46325
+ if (!org)
46326
+ signUp.metadata.org = "";
46327
+ }
46328
+ if (signUp.metadata?.siteId)
46329
+ await getSiteById(signUp.metadata?.siteId);
46330
+ const user = {
46331
+ email,
46332
+ password: signUp.metadata?.password,
46333
+ name,
46334
+ defaultOrg: org?._id?.toString() || ""
46335
+ };
46336
+ const userId = await _createUser(user, session);
46337
+ if (org?._id) {
46338
+ await addMember(
46339
+ {
46340
+ org: org?._id?.toString() || "",
46341
+ orgName: org?.name || "",
46342
+ user: userId.toString(),
46343
+ name,
46344
+ role: signUp.metadata?.role?.toString() || "",
46345
+ type: signUp.metadata?.app ?? "organization",
46346
+ siteId: signUp.metadata?.siteId?.toString() || "",
46347
+ siteName: signUp.metadata?.siteName || ""
46348
+ },
46349
+ session
46350
+ );
46351
+ }
46352
+ await _updateVerificationStatusById(
46353
+ id,
46354
+ "complete" /* COMPLETE */,
46355
+ session
46356
+ );
46357
+ await session?.commitTransaction();
46358
+ return userId;
46359
+ } catch (error) {
46360
+ await session?.abortTransaction();
46361
+ throw error;
46362
+ } finally {
46363
+ session?.endSession();
46364
+ }
46365
+ }
46366
+ async function resetPassword(id, newPassword, passwordConfirmation) {
46367
+ if (newPassword !== passwordConfirmation) {
46368
+ throw new import_node_server_utils222.BadRequestError("Passwords do not match.");
46369
+ }
46370
+ let hashedPassword;
46371
+ const session = import_node_server_utils222.useAtlas.getClient()?.startSession();
46372
+ session?.startTransaction();
46373
+ try {
46374
+ hashedPassword = await (0, import_node_server_utils222.hashPassword)(newPassword);
46375
+ } catch (error) {
46376
+ throw new import_node_server_utils222.InternalServerError(`Error hashing password: ${error}`);
46377
+ }
46378
+ try {
46379
+ const otpDoc = await _getVerificationById(id);
46380
+ if (!otpDoc) {
46381
+ throw new import_node_server_utils222.NotFoundError("You are using an invalid reset link.");
46382
+ }
46383
+ if (otpDoc.status === "complete" /* COMPLETE */) {
46384
+ throw new import_node_server_utils222.BadRequestError("This link has already been invalidated.");
46385
+ }
46386
+ const user = await _getUserByEmail(otpDoc.email);
46387
+ if (!user) {
46388
+ throw new import_node_server_utils222.NotFoundError("User not found.");
46389
+ }
46390
+ if (!user._id) {
46391
+ throw new import_node_server_utils222.InternalServerError("Invalid user ID.");
46392
+ }
46393
+ await Promise.all([
46394
+ _updateVerificationStatusById(id, "complete" /* COMPLETE */, session),
46395
+ _updatePasswordById(
46396
+ { _id: user._id.toString(), password: hashedPassword },
46397
+ session
46398
+ )
46399
+ ]);
46400
+ await session?.commitTransaction();
46401
+ return "Successfully reset password.";
46402
+ } catch (error) {
46403
+ await session?.abortTransaction();
46404
+ throw error;
46405
+ } finally {
46406
+ session?.endSession();
46407
+ }
46408
+ }
46409
+ const s3 = new import_node_server_utils222.useS3({
46410
+ accessKeyId: SPACES_ACCESS_KEY,
46411
+ secretAccessKey: SPACES_SECRET_KEY,
46412
+ endpoint: SPACES_ENDPOINT,
46413
+ region: SPACES_REGION,
46414
+ bucket: SPACES_BUCKET,
46415
+ forcePathStyle: false
46416
+ });
46417
+ async function updateUserProfile({
46418
+ file,
46419
+ user,
46420
+ previousProfile
46421
+ }) {
46422
+ const session = import_node_server_utils222.useAtlas.getClient()?.startSession();
46423
+ session?.startTransaction();
46424
+ const _file = {
46425
+ name: file.originalname,
46426
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
46427
+ };
46428
+ try {
46429
+ const id = await createFile(_file, session);
46430
+ await s3.uploadObject({
46431
+ key: id,
46432
+ body: file.buffer,
46433
+ contentType: file.mimetype
46434
+ });
46435
+ if (previousProfile) {
46436
+ await deleteFileById(previousProfile, session);
46437
+ await s3.deleteObject(previousProfile);
46438
+ }
46439
+ await _updateUserFieldById(
46440
+ { _id: user, field: "profile", value: id },
46441
+ session
46442
+ );
46443
+ await session?.commitTransaction();
46444
+ return id;
46445
+ } catch (error) {
46446
+ await session?.abortTransaction();
46447
+ throw error;
46448
+ } finally {
46449
+ session?.endSession();
46450
+ }
46451
+ }
46452
+ async function updatePasswordById(id, currentPassword, newPassword, passwordConfirmation) {
46453
+ let hashedPassword;
46454
+ const user = await getUserById(id);
46455
+ const isPasswordValid = await (0, import_node_server_utils222.comparePassword)(
46456
+ currentPassword,
46457
+ user.password
46458
+ );
46459
+ if (!isPasswordValid)
46460
+ throw new import_node_server_utils222.BadRequestError("Invalid current password.");
46461
+ if (newPassword !== passwordConfirmation)
46462
+ throw new import_node_server_utils222.BadRequestError("Passwords do not match.");
46463
+ try {
46464
+ hashedPassword = await (0, import_node_server_utils222.hashPassword)(newPassword);
46465
+ if (!hashedPassword)
46466
+ throw new import_node_server_utils222.InternalServerError("Error hashing password.");
46467
+ return await updatePassword({ _id: id, password: hashedPassword });
46468
+ } catch (error) {
46469
+ throw error;
46470
+ }
46471
+ }
46472
+ return {
46473
+ createUserBySignUp,
46474
+ resetPassword,
46475
+ updateUserProfile,
46476
+ updatePasswordById
46477
+ };
46478
+ }
46479
+
46023
46480
  // src/controllers/auth-v2.controller.ts
46024
46481
  function useAuthControllerV2() {
46025
46482
  const { signUp: _signUp } = useVerificationServiceV2();
46026
46483
  const { login: _login, logout: _logout } = useAuthServiceV2();
46484
+ const { resetPassword: _resetPassword } = useUserServiceV2();
46027
46485
  async function signUp(req, res, next) {
46028
46486
  try {
46029
46487
  const validation = import_joi127.default.object({
@@ -46037,8 +46495,8 @@ function useAuthControllerV2() {
46037
46495
  });
46038
46496
  if (error) {
46039
46497
  const messages = error.details.map((d) => d.message);
46040
- import_node_server_utils222.logger.log({ level: "error", message: messages.join(", ") });
46041
- next(new import_node_server_utils222.BadRequestError(messages.join(", ")));
46498
+ import_node_server_utils223.logger.log({ level: "error", message: messages.join(", ") });
46499
+ next(new import_node_server_utils223.BadRequestError(messages.join(", ")));
46042
46500
  return;
46043
46501
  }
46044
46502
  const { email, password, country, orgName } = value;
@@ -46054,7 +46512,7 @@ function useAuthControllerV2() {
46054
46512
  return;
46055
46513
  } catch (error) {
46056
46514
  console.log(error);
46057
- import_node_server_utils222.logger.log({ level: "error", message: error.message });
46515
+ import_node_server_utils223.logger.log({ level: "error", message: error.message });
46058
46516
  next(error);
46059
46517
  return;
46060
46518
  }
@@ -46072,8 +46530,8 @@ function useAuthControllerV2() {
46072
46530
  });
46073
46531
  if (error) {
46074
46532
  const messages = error.details.map((d) => d.message);
46075
- import_node_server_utils222.logger.log({ level: "error", message: messages.join(", ") });
46076
- next(new import_node_server_utils222.BadRequestError(messages.join(", ")));
46533
+ import_node_server_utils223.logger.log({ level: "error", message: messages.join(", ") });
46534
+ next(new import_node_server_utils223.BadRequestError(messages.join(", ")));
46077
46535
  return;
46078
46536
  }
46079
46537
  const session = await _login(value);
@@ -46085,7 +46543,7 @@ function useAuthControllerV2() {
46085
46543
  res.cookie("sid", session.sid, cookieOptions).cookie("user", session.user, cookieOptions).json(session);
46086
46544
  return;
46087
46545
  } catch (error) {
46088
- import_node_server_utils222.logger.log({ level: "error", message: error.message });
46546
+ import_node_server_utils223.logger.log({ level: "error", message: error.message });
46089
46547
  next(error);
46090
46548
  return;
46091
46549
  }
@@ -46093,7 +46551,7 @@ function useAuthControllerV2() {
46093
46551
  async function logout(req, res, next) {
46094
46552
  const sid = req.headers["authorization"] ?? "";
46095
46553
  if (!sid) {
46096
- next(new import_node_server_utils222.BadRequestError("Session ID is required"));
46554
+ next(new import_node_server_utils223.BadRequestError("Session ID is required"));
46097
46555
  return;
46098
46556
  }
46099
46557
  try {
@@ -46101,127 +46559,170 @@ function useAuthControllerV2() {
46101
46559
  res.json({ message: "Logged out successfully" });
46102
46560
  return;
46103
46561
  } catch (error) {
46104
- import_node_server_utils222.logger.log({ level: "error", message: error.message });
46562
+ import_node_server_utils223.logger.log({ level: "error", message: error.message });
46105
46563
  next(error);
46106
46564
  return;
46107
46565
  }
46108
46566
  }
46109
- return {
46110
- signUp,
46111
- login,
46112
- logout
46113
- };
46114
- }
46115
-
46116
- // src/services/user-v2.service.ts
46117
- var import_node_server_utils223 = require("@7365admin1/node-server-utils");
46118
- var import_multer2 = require("multer");
46119
- function useUserServiceV2() {
46120
- const { createUser: _createUser, getUserByEmail } = useUserRepoV2();
46121
- const { getRoleByName, addRole } = useRoleRepo();
46122
- const { add: addMember } = useMemberRepo();
46123
- const { getById: getOrgById } = useOrgRepo();
46124
- const { getSiteById } = useSiteRepo();
46125
- const {
46126
- getVerificationById: _getVerificationById,
46127
- updateVerificationStatusById: _updateVerificationStatusById
46128
- } = useVerificationRepoV2();
46129
- const { verify } = useVerificationService();
46130
- const { createFile, deleteFileById } = useFileRepo();
46131
- async function createUserBySignUp({
46132
- id = "",
46133
- name = ""
46134
- }) {
46135
- const session = import_node_server_utils223.useAtlas.getClient()?.startSession();
46136
- session?.startTransaction();
46567
+ async function resetPassword(req, res, next) {
46568
+ const validation = import_joi127.default.object({
46569
+ otp: import_joi127.default.string().hex().required(),
46570
+ newPassword: import_joi127.default.string().required().min(8),
46571
+ passwordConfirmation: import_joi127.default.string().required().min(8)
46572
+ });
46573
+ const { error, value } = validation.validate(req.body, {
46574
+ abortEarly: false
46575
+ });
46576
+ if (error) {
46577
+ const messages = error.details.map((d) => d.message);
46578
+ import_node_server_utils223.logger.log({ level: "error", message: messages.join(", ") });
46579
+ next(new import_node_server_utils223.BadRequestError(messages.join(", ")));
46580
+ return;
46581
+ }
46582
+ const { otp, newPassword, passwordConfirmation } = value;
46137
46583
  try {
46138
- const signUp = await _getVerificationById(id);
46139
- if (!signUp)
46140
- throw new import_node_server_utils223.BadRequestError("Invalid sign up link.");
46141
- if (signUp.status === "complete")
46142
- throw new import_node_server_utils223.BadRequestError(
46143
- "You have already an account created using this link."
46144
- );
46145
- const expired = signUp.expireAt < (/* @__PURE__ */ new Date()).toISOString();
46146
- if (signUp.status === "expired" || expired)
46147
- throw new import_node_server_utils223.BadRequestError("Sign up link expired.");
46148
- const email = signUp.email;
46149
- const _user = await getUserByEmail(email);
46150
- if (_user)
46151
- throw new import_node_server_utils223.BadRequestError(`User already exists: ${email}.`);
46152
- let org = null;
46153
- if (signUp.metadata?.org) {
46154
- org = await getOrgById(signUp.metadata.org);
46155
- if (!org)
46156
- signUp.metadata.org = "";
46157
- }
46158
- if (signUp.metadata?.siteId)
46159
- await getSiteById(signUp.metadata?.siteId);
46160
- const user = {
46161
- email,
46162
- password: signUp.metadata?.password,
46163
- name,
46164
- defaultOrg: org?._id?.toString() || ""
46165
- };
46166
- const userId = await _createUser(user, session);
46167
- if (org?._id) {
46168
- await addMember(
46169
- {
46170
- org: org?._id?.toString() || "",
46171
- orgName: org?.name || "",
46172
- user: userId.toString(),
46173
- name,
46174
- role: signUp.metadata?.role?.toString() || "",
46175
- type: signUp.metadata?.app ?? "organization",
46176
- siteId: signUp.metadata?.siteId?.toString() || "",
46177
- siteName: signUp.metadata?.siteName || ""
46178
- },
46179
- session
46180
- );
46181
- }
46182
- await _updateVerificationStatusById(
46183
- id,
46184
- "complete" /* COMPLETE */,
46185
- session
46584
+ const message = await _resetPassword(
46585
+ otp,
46586
+ newPassword,
46587
+ passwordConfirmation
46186
46588
  );
46187
- await session?.commitTransaction();
46188
- return userId;
46189
- } catch (error) {
46190
- await session?.abortTransaction();
46191
- throw error;
46192
- } finally {
46193
- session?.endSession();
46589
+ res.json({ message });
46590
+ return;
46591
+ } catch (error2) {
46592
+ import_node_server_utils223.logger.log({ level: "error", message: error2.message });
46593
+ next(error2);
46594
+ return;
46194
46595
  }
46195
46596
  }
46196
46597
  return {
46197
- createUserBySignUp
46598
+ signUp,
46599
+ login,
46600
+ logout,
46601
+ resetPassword
46198
46602
  };
46199
46603
  }
46200
46604
 
46201
46605
  // src/controllers/user-v2.controller.ts
46202
46606
  var import_joi128 = __toESM(require("joi"));
46607
+ var import_multer3 = require("multer");
46203
46608
  var import_node_server_utils224 = require("@7365admin1/node-server-utils");
46204
46609
  function useUserControllerV2() {
46205
- const { createUserBySignUp: _createUserBySignUp } = useUserServiceV2();
46610
+ const {
46611
+ updateBirthday: _updateBirthday,
46612
+ getUserById: _getUserById,
46613
+ getUserByEmail: _getUserByEmail,
46614
+ getUserById: _getById,
46615
+ getUsers: _getUsers,
46616
+ getUsersByOrgId: _getUsersByOrgId,
46617
+ updateUserFieldById: _updateUserFieldById
46618
+ } = useUserRepoV2();
46619
+ const { createUserBySignUp, updateUserProfile: _updateUserProfile, updatePasswordById: _updatePasswordById } = useUserServiceV2();
46620
+ function rejectValidation(error, next) {
46621
+ const message = error.details.map((d) => d.message).join(", ");
46622
+ import_node_server_utils224.logger.log({ level: "error", message });
46623
+ next(new import_node_server_utils224.BadRequestError(message));
46624
+ }
46625
+ async function getById(req, res, next) {
46626
+ const validation = import_joi128.default.string().hex().required();
46627
+ const _id = req.params.id;
46628
+ const { error, value } = validation.validate(_id);
46629
+ if (error) {
46630
+ import_node_server_utils224.logger.log({ level: "error", message: `${error.message}` });
46631
+ next(new import_node_server_utils224.BadRequestError(error.message));
46632
+ return;
46633
+ }
46634
+ try {
46635
+ const user = await _getById(value);
46636
+ res.json(user);
46637
+ return;
46638
+ } catch (error2) {
46639
+ import_node_server_utils224.logger.log({ level: "error", message: `${error2.message}` });
46640
+ next(error2);
46641
+ return;
46642
+ }
46643
+ }
46644
+ async function getByEmail(req, res, next) {
46645
+ const { error, value } = import_joi128.default.string().email().required().validate(req.params.email);
46646
+ if (error)
46647
+ return rejectValidation(error, next);
46648
+ try {
46649
+ const user = await _getUserByEmail(value);
46650
+ res.json(user);
46651
+ return;
46652
+ } catch (err) {
46653
+ import_node_server_utils224.logger.log({ level: "error", message: `${err.message}` });
46654
+ next(err);
46655
+ return;
46656
+ }
46657
+ }
46658
+ async function getUsers(req, res, next) {
46659
+ const { search = "", page = 1, limit = 10, sort = {}, type = "", status = "active" } = req.query;
46660
+ const { error, value } = import_joi128.default.object({
46661
+ search: import_joi128.default.string().optional().allow("", null),
46662
+ page: import_joi128.default.number().integer().min(1).allow("", null).default(1),
46663
+ limit: import_joi128.default.number().integer().min(1).allow("", null).default(10),
46664
+ sort: import_joi128.default.object().optional().allow("", null).default({}),
46665
+ type: import_joi128.default.string().optional().allow("", null).default(""),
46666
+ status: import_joi128.default.string().optional().allow("", null).default("active" /* ACTIVE */)
46667
+ }).validate({ search, page, limit, sort, type, status });
46668
+ if (error)
46669
+ return rejectValidation(error, next);
46670
+ try {
46671
+ const users = await _getUsers({
46672
+ search: value.search ?? "",
46673
+ page: value.page,
46674
+ limit: value.limit,
46675
+ sort: value.sort,
46676
+ type: value.type,
46677
+ status: value.status
46678
+ });
46679
+ res.json(users);
46680
+ return;
46681
+ } catch (err) {
46682
+ next(err);
46683
+ }
46684
+ }
46685
+ async function getUsersByOrgId(req, res, next) {
46686
+ const { search, page, status, organization } = req.query;
46687
+ const { error, value } = import_joi128.default.object({
46688
+ search: import_joi128.default.string().optional().allow("", null),
46689
+ page: import_joi128.default.number().integer().min(1).allow("", null).default(1),
46690
+ status: import_joi128.default.string().required(),
46691
+ organization: import_joi128.default.string().required()
46692
+ }).validate({ search, page, status, organization });
46693
+ if (error)
46694
+ return rejectValidation(error, next);
46695
+ try {
46696
+ res.json(
46697
+ await _getUsersByOrgId({
46698
+ search: value.search ?? "",
46699
+ page: value.page,
46700
+ status: value.status,
46701
+ organization: value.organization
46702
+ })
46703
+ );
46704
+ } catch (err) {
46705
+ next(err);
46706
+ }
46707
+ }
46206
46708
  async function createUserByVerification(req, res, next) {
46207
- const schema2 = import_joi128.default.object({
46208
- id: import_joi128.default.string().hex().length(24).required(),
46709
+ const allowedTypes = ["user-sign-up" /* USER_SIGN_UP */, "user-invite" /* USER_INVITE */];
46710
+ const validation = import_joi128.default.object({
46711
+ id: import_joi128.default.string().hex().required(),
46209
46712
  name: import_joi128.default.string().required(),
46210
- type: import_joi128.default.string().required().valid("user-sign-up" /* USER_SIGN_UP */, "user-invite" /* USER_INVITE */)
46211
- });
46212
- const { error, value } = schema2.validate({
46213
- id: req.params.id,
46214
- ...req.body
46713
+ password: import_joi128.default.string().required(),
46714
+ type: import_joi128.default.string().required().valid(...allowedTypes)
46215
46715
  });
46716
+ const id = req.params.id;
46717
+ const payload = { ...req.body };
46718
+ const { error, value } = validation.validate({ id, ...payload });
46216
46719
  if (error) {
46217
- const messages = error.details.map((d) => d.message).join(", ");
46218
- import_node_server_utils224.logger.log({ level: "error", message: messages });
46219
- next(new import_node_server_utils224.BadRequestError(messages));
46720
+ import_node_server_utils224.logger.log({ level: "error", message: `${error.message}` });
46721
+ next(new import_node_server_utils224.BadRequestError(error.message));
46220
46722
  return;
46221
46723
  }
46222
- const { id, name } = value;
46223
46724
  try {
46224
- await _createUserBySignUp({ id, name });
46725
+ await createUserBySignUp({ id: value.id, name: value.name });
46225
46726
  res.status(201).json({ message: "Successfully created account." });
46226
46727
  return;
46227
46728
  } catch (error2) {
@@ -46230,8 +46731,148 @@ function useUserControllerV2() {
46230
46731
  return;
46231
46732
  }
46232
46733
  }
46734
+ async function updateUserProfile(req, res, next) {
46735
+ if (!req.file) {
46736
+ next(new import_node_server_utils224.BadRequestError("File is required!"));
46737
+ return;
46738
+ }
46739
+ const validation = import_joi128.default.object({
46740
+ previousProfile: import_joi128.default.string().hex().optional().allow("", null)
46741
+ });
46742
+ const payload = { ...req.body };
46743
+ const { error, value } = validation.validate(payload);
46744
+ if (error) {
46745
+ import_node_server_utils224.logger.log({ level: "error", message: `${error.message}` });
46746
+ next(new import_node_server_utils224.BadRequestError(error.message));
46747
+ return;
46748
+ }
46749
+ const user = req.headers.user ?? "";
46750
+ try {
46751
+ await _updateUserProfile({
46752
+ file: req.file,
46753
+ user,
46754
+ ...value
46755
+ });
46756
+ res.json({ message: "Successfully updated profile picture." });
46757
+ return;
46758
+ } catch (error2) {
46759
+ import_node_server_utils224.logger.log({ level: "error", message: `${error2.message}` });
46760
+ next(error2);
46761
+ return;
46762
+ }
46763
+ }
46764
+ async function updateBirthday(req, res, next) {
46765
+ const MONTHS = [
46766
+ "January",
46767
+ "February",
46768
+ "March",
46769
+ "April",
46770
+ "May",
46771
+ "June",
46772
+ "July",
46773
+ "August",
46774
+ "September",
46775
+ "October",
46776
+ "November",
46777
+ "December"
46778
+ ];
46779
+ const validation = import_joi128.default.object({
46780
+ _id: import_joi128.default.string().hex().required(),
46781
+ month: import_joi128.default.string().valid(...MONTHS).required(),
46782
+ day: import_joi128.default.number().integer().min(1).max(31).required(),
46783
+ year: import_joi128.default.number().integer().min(1900).max((/* @__PURE__ */ new Date()).getFullYear()).required()
46784
+ });
46785
+ const _id = req.params.id;
46786
+ const payload = { ...req.body };
46787
+ const { error } = validation.validate({ _id, ...payload });
46788
+ if (error) {
46789
+ import_node_server_utils224.logger.log({ level: "error", message: `${error.message}` });
46790
+ next(new import_node_server_utils224.BadRequestError(error.message));
46791
+ return;
46792
+ }
46793
+ try {
46794
+ const message = await _updateBirthday({ _id, ...payload });
46795
+ res.json({ message });
46796
+ return;
46797
+ } catch (error2) {
46798
+ import_node_server_utils224.logger.log({ level: "error", message: `${error2.message}` });
46799
+ next(error2);
46800
+ return;
46801
+ }
46802
+ }
46803
+ async function updateUserFieldById(req, res, next) {
46804
+ const FIELDS = ["name", "email", "contact", "nric", "dateOfBirth", "profile", "gender", "defaultOrg"];
46805
+ const validation = import_joi128.default.object({
46806
+ _id: import_joi128.default.string().hex().required(),
46807
+ field: import_joi128.default.string().valid(...FIELDS).required(),
46808
+ value: import_joi128.default.when("field", {
46809
+ switch: [
46810
+ { is: "email", then: import_joi128.default.string().email().required() },
46811
+ { is: "defaultOrg", then: import_joi128.default.string().hex().required() }
46812
+ ],
46813
+ otherwise: import_joi128.default.string().required()
46814
+ })
46815
+ });
46816
+ const _id = req.params.id;
46817
+ const payload = { ...req.body };
46818
+ const { error } = validation.validate({ _id, ...payload });
46819
+ if (error) {
46820
+ import_node_server_utils224.logger.log({ level: "error", message: `${error.message}` });
46821
+ next(new import_node_server_utils224.BadRequestError(error.message));
46822
+ return;
46823
+ }
46824
+ try {
46825
+ const message = await _updateUserFieldById({ _id, ...payload });
46826
+ res.json({ message });
46827
+ return;
46828
+ } catch (error2) {
46829
+ import_node_server_utils224.logger.log({ level: "error", message: `${error2.message}` });
46830
+ next(error2);
46831
+ return;
46832
+ }
46833
+ }
46834
+ async function updatePasswordById(req, res, next) {
46835
+ const validation = import_joi128.default.object({
46836
+ _id: import_joi128.default.string().hex().required(),
46837
+ currentPassword: import_joi128.default.string().required().min(8),
46838
+ newPassword: import_joi128.default.string().required().min(8),
46839
+ passwordConfirmation: import_joi128.default.string().required().min(8)
46840
+ });
46841
+ const _id = req.params.id;
46842
+ const payload = { ...req.body };
46843
+ const { error } = validation.validate({
46844
+ _id,
46845
+ ...payload
46846
+ });
46847
+ if (error) {
46848
+ next(new import_node_server_utils224.BadRequestError(error.message));
46849
+ return;
46850
+ }
46851
+ const currentPassword = req.body.currentPassword ?? "";
46852
+ const newPassword = req.body.newPassword ?? "";
46853
+ const passwordConfirmation = req.body.passwordConfirmation ?? "";
46854
+ try {
46855
+ await _updatePasswordById(
46856
+ _id,
46857
+ currentPassword,
46858
+ newPassword,
46859
+ passwordConfirmation
46860
+ );
46861
+ res.json({ message: "Successfully updated password." });
46862
+ } catch (error2) {
46863
+ next(error2);
46864
+ }
46865
+ }
46233
46866
  return {
46234
- createUserByVerification
46867
+ getById,
46868
+ getByEmail,
46869
+ getUsersByOrgId,
46870
+ getUsers,
46871
+ createUserByVerification,
46872
+ updateUserProfile,
46873
+ updateBirthday,
46874
+ updateUserFieldById,
46875
+ updatePasswordById
46235
46876
  };
46236
46877
  }
46237
46878
  // Annotate the CommonJS export names for ESM import in node:
@@ -46374,6 +47015,7 @@ function useUserControllerV2() {
46374
47015
  occurrence_book_namespace_collection,
46375
47016
  orgSchema,
46376
47017
  overnight_parking_requests_namespace_collection,
47018
+ parseDahuaFind,
46377
47019
  pestDashboardCollection,
46378
47020
  poolDashboardCollection,
46379
47021
  promoCodeSchema,