@7365admin1/core 2.29.0 → 2.30.1

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).optional().allow(null, ""),
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,
@@ -2233,32 +2241,16 @@ function useOccurrenceEntryRepo() {
2233
2241
  throw error;
2234
2242
  }
2235
2243
  }
2236
- async function getOccurrenceEntryByBookId(dailyOccurrenceBookId, session) {
2244
+ async function getOccurrenceEntryByBookId(dailyOccurrenceBookId) {
2237
2245
  try {
2238
2246
  dailyOccurrenceBookId = new import_mongodb7.ObjectId(dailyOccurrenceBookId);
2239
2247
  } catch (error) {
2240
2248
  throw new import_node_server_utils8.BadRequestError("Invalid occurrence entry ID format.");
2241
2249
  }
2242
- const cacheKey = (0, import_node_server_utils8.makeCacheKey)(namespace_collection, {
2243
- dailyOccurrenceBookId
2244
- });
2245
- const cachedData = await getCache(cacheKey);
2246
- if (cachedData) {
2247
- import_node_server_utils8.logger.info(`Cache hit for key: ${cacheKey}`);
2248
- return cachedData;
2249
- }
2250
+ const query = { dailyOccurrenceBookId };
2250
2251
  try {
2251
- const data = await collection.findOne(
2252
- { dailyOccurrenceBookId },
2253
- {
2254
- sort: { _id: -1 },
2255
- session
2256
- }
2257
- );
2258
- setCache(cacheKey, data, 15 * 60).then(() => {
2259
- import_node_server_utils8.logger.info(`Cache set for key: ${cacheKey}`);
2260
- }).catch((err) => {
2261
- import_node_server_utils8.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
2252
+ const data = await collection.findOne(query, {
2253
+ sort: { _id: -1 }
2262
2254
  });
2263
2255
  return data;
2264
2256
  } catch (error) {
@@ -13099,6 +13091,7 @@ var PersonTypes = /* @__PURE__ */ ((PersonTypes3) => {
13099
13091
  PersonTypes3["GUEST"] = "guest";
13100
13092
  PersonTypes3["TENANT"] = "tenant";
13101
13093
  PersonTypes3["RESIDENT"] = "resident";
13094
+ PersonTypes3["VISITOR"] = "visitor";
13102
13095
  return PersonTypes3;
13103
13096
  })(PersonTypes || {});
13104
13097
  var PersonStatus = /* @__PURE__ */ ((PersonStatus2) => {
@@ -13286,7 +13279,6 @@ var schemaVisitorTransaction = import_joi36.default.object({
13286
13279
  contact: import_joi36.default.string().optional().allow(null, "")
13287
13280
  })
13288
13281
  ).optional().allow(null),
13289
- visitorPass: import_joi36.default.string().optional().allow(null, ""),
13290
13282
  unitName: import_joi36.default.string().optional().allow(null, ""),
13291
13283
  expiredAt: import_joi36.default.date().iso().optional().allow(null, ""),
13292
13284
  arrivalTime: import_joi36.default.string().pattern(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().allow(null, "").messages({
@@ -13295,7 +13287,15 @@ var schemaVisitorTransaction = import_joi36.default.object({
13295
13287
  duration: import_joi36.default.number().integer().optional().allow(null),
13296
13288
  isOvernightParking: import_joi36.default.boolean().optional().default(false),
13297
13289
  email: import_joi36.default.string().email().optional().allow(null, ""),
13298
- numberOfPassengers: import_joi36.default.number().integer().optional().allow(null, "")
13290
+ numberOfPassengers: import_joi36.default.number().integer().optional().allow(null, ""),
13291
+ visitorPass: import_joi36.default.array().items(
13292
+ import_joi36.default.string().hex().length(24).optional().allow(null)
13293
+ ),
13294
+ passKeys: import_joi36.default.array().items(
13295
+ import_joi36.default.string().hex().length(24).optional().allow(null)
13296
+ ),
13297
+ checkInRemarks: import_joi36.default.string().optional().allow("", null),
13298
+ checkOutRemarks: import_joi36.default.string().optional().allow("", null)
13299
13299
  });
13300
13300
  var schemaUpdateVisTrans = import_joi36.default.object({
13301
13301
  _id: import_joi36.default.string().hex().length(24).required(),
@@ -13321,7 +13321,15 @@ var schemaUpdateVisTrans = import_joi36.default.object({
13321
13321
  status: import_joi36.default.string().optional().allow(null, ""),
13322
13322
  remarks: import_joi36.default.string().optional().allow(null, ""),
13323
13323
  manualCheckout: import_joi36.default.boolean().optional().allow(null),
13324
- expiredAt: import_joi36.default.date().iso().optional().allow(null, "")
13324
+ expiredAt: import_joi36.default.date().iso().optional().allow(null, ""),
13325
+ visitorPass: import_joi36.default.array().items(
13326
+ import_joi36.default.string().hex().length(24).optional().allow(null)
13327
+ ),
13328
+ passKeys: import_joi36.default.array().items(
13329
+ import_joi36.default.string().hex().length(24).optional().allow(null)
13330
+ ),
13331
+ checkInRemarks: import_joi36.default.string().optional().allow("", null),
13332
+ checkOutRemarks: import_joi36.default.string().optional().allow("", null)
13325
13333
  });
13326
13334
  function MVisitorTransaction(value) {
13327
13335
  const { error } = schemaVisitorTransaction.validate(value, {
@@ -13365,6 +13373,14 @@ function MVisitorTransaction(value) {
13365
13373
  throw new Error("Invalid type for manualCheckout key.");
13366
13374
  }
13367
13375
  }
13376
+ if (value.visitorPass && Array.isArray(value.visitorPass) && value.visitorPass.length > 0)
13377
+ value.visitorPass = value.visitorPass.map(
13378
+ (v) => typeof v === "string" ? new import_mongodb39.ObjectId(v) : v
13379
+ );
13380
+ if (value.passKeys && Array.isArray(value.passKeys) && value.passKeys.length > 0)
13381
+ value.passKeys = value.passKeys.map(
13382
+ (p) => typeof p === "string" ? new import_mongodb39.ObjectId(p) : p
13383
+ );
13368
13384
  const newDate = (/* @__PURE__ */ new Date()).toISOString();
13369
13385
  return {
13370
13386
  _id: value._id,
@@ -13391,7 +13407,10 @@ function MVisitorTransaction(value) {
13391
13407
  contractorType: value.contractorType,
13392
13408
  manualCheckout: value.manualCheckout ?? false,
13393
13409
  direction: value.direction,
13394
- visitorPass: value.visitorPass,
13410
+ visitorPass: value.visitorPass ?? [],
13411
+ passKeys: value.passKeys ?? [],
13412
+ checkInRemarks: value.checkInRemarks,
13413
+ checkOutRemarks: value.checkOutRemarks,
13395
13414
  unitName: value.unitName,
13396
13415
  expiredAt: value.expiredAt ?? null,
13397
13416
  createdAt: value.createdAt ?? newDate,
@@ -13409,9 +13428,6 @@ function useVisitorTransactionRepo() {
13409
13428
  throw new import_node_server_utils68.InternalServerError("Unable to connect to server.");
13410
13429
  }
13411
13430
  const collection = db.collection(visitors_namespace_collection);
13412
- const { delNamespace, getCache, setCache } = (0, import_node_server_utils68.useCache)(
13413
- visitors_namespace_collection
13414
- );
13415
13431
  async function createTextIndex() {
13416
13432
  try {
13417
13433
  await collection.createIndex({
@@ -13432,16 +13448,6 @@ function useVisitorTransactionRepo() {
13432
13448
  try {
13433
13449
  value = MVisitorTransaction(value);
13434
13450
  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
13451
  return res.insertedId;
13446
13452
  } catch (error) {
13447
13453
  const isDuplicated = error.message.includes("duplicate");
@@ -13464,7 +13470,7 @@ function useVisitorTransactionRepo() {
13464
13470
  type = "",
13465
13471
  checkedOut,
13466
13472
  plateNumber = ""
13467
- }, session) {
13473
+ }) {
13468
13474
  page = page > 0 ? page - 1 : 0;
13469
13475
  const skip = page * limit;
13470
13476
  let checkOutFilter;
@@ -13499,26 +13505,6 @@ function useVisitorTransactionRepo() {
13499
13505
  ...plateNumber && { plateNumber }
13500
13506
  };
13501
13507
  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
13508
  try {
13523
13509
  const basePipeline = [{ $match: query }];
13524
13510
  const [items, countResult] = await Promise.all([
@@ -13562,23 +13548,12 @@ function useVisitorTransactionRepo() {
13562
13548
  ]);
13563
13549
  const totalCount = countResult[0]?.total || 0;
13564
13550
  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
13551
  return data;
13571
13552
  } catch (error) {
13572
13553
  throw error;
13573
13554
  }
13574
13555
  }
13575
13556
  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
13557
  const _id = (0, import_node_server_utils68.toObjectId)(id);
13583
13558
  try {
13584
13559
  const basePipeline = [{ $match: { _id } }];
@@ -13615,38 +13590,20 @@ function useVisitorTransactionRepo() {
13615
13590
  }
13616
13591
  }
13617
13592
  ]).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
13593
  return result;
13624
13594
  } catch (error) {
13625
13595
  throw error;
13626
13596
  }
13627
13597
  }
13628
13598
  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, {
13599
+ const _site = typeof site === "string" ? (0, import_node_server_utils68.toObjectId)(site) : site;
13600
+ const query = {
13631
13601
  plateNumber,
13632
- key: "get-open-transaction-plate-number",
13633
- site
13634
- });
13602
+ site: _site,
13603
+ checkOut: null
13604
+ };
13635
13605
  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
- });
13606
+ const data = await collection.findOne(query);
13650
13607
  return data;
13651
13608
  } catch (error) {
13652
13609
  throw new import_node_server_utils68.InternalServerError(
@@ -13670,16 +13627,6 @@ function useVisitorTransactionRepo() {
13670
13627
  { $set: value },
13671
13628
  { session }
13672
13629
  );
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
13630
  return result;
13684
13631
  } catch (error) {
13685
13632
  throw error;
@@ -13701,16 +13648,6 @@ function useVisitorTransactionRepo() {
13701
13648
  if (res.modifiedCount === 0) {
13702
13649
  throw new import_node_server_utils68.InternalServerError("Unable to delete visitor transaction.");
13703
13650
  }
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
13651
  return res.modifiedCount;
13715
13652
  } catch (error) {
13716
13653
  throw error;
@@ -13776,16 +13713,6 @@ function useVisitorTransactionRepo() {
13776
13713
  },
13777
13714
  { session }
13778
13715
  );
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
13716
  return res;
13790
13717
  } catch (error) {
13791
13718
  throw error;
@@ -13817,6 +13744,7 @@ var VehicleType = /* @__PURE__ */ ((VehicleType2) => {
13817
13744
  var VehicleCategory = /* @__PURE__ */ ((VehicleCategory2) => {
13818
13745
  VehicleCategory2["RESIDENT"] = "resident";
13819
13746
  VehicleCategory2["VISITOR"] = "visitor";
13747
+ VehicleCategory2["GUEST"] = "guest";
13820
13748
  return VehicleCategory2;
13821
13749
  })(VehicleCategory || {});
13822
13750
  var VehicleStatus = /* @__PURE__ */ ((VehicleStatus2) => {
@@ -13861,7 +13789,7 @@ var vehicleSchema = import_joi37.default.object({
13861
13789
  return value;
13862
13790
  }).required(),
13863
13791
  type: import_joi37.default.string().required().valid(...Object.values(VehicleType)),
13864
- category: import_joi37.default.string().required().valid(...Object.values(VehicleCategory)),
13792
+ category: import_joi37.default.string().required().valid(...Object.values(PersonTypes)),
13865
13793
  name: import_joi37.default.string().required(),
13866
13794
  phoneNumber: import_joi37.default.string().optional().allow("", null),
13867
13795
  recNo: import_joi37.default.string().optional().allow("", null),
@@ -14005,9 +13933,6 @@ function useVehicleRepo() {
14005
13933
  throw new import_node_server_utils70.InternalServerError("Unable to connect to server.");
14006
13934
  }
14007
13935
  const collection = db.collection(vehicles_namespace_collection);
14008
- const { delNamespace, setCache, getCache } = (0, import_node_server_utils70.useCache)(
14009
- vehicles_namespace_collection
14010
- );
14011
13936
  async function createIndex() {
14012
13937
  try {
14013
13938
  await collection.createIndexes([
@@ -14039,16 +13964,6 @@ function useVehicleRepo() {
14039
13964
  try {
14040
13965
  value = MVehicle(value);
14041
13966
  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
13967
  return res.insertedId;
14053
13968
  } catch (error) {
14054
13969
  import_node_server_utils70.logger.log({
@@ -14073,29 +13988,12 @@ function useVehicleRepo() {
14073
13988
  }) {
14074
13989
  page = page > 0 ? page - 1 : 0;
14075
13990
  const baseQuery = {
14076
- ...status && { status },
14077
- ...type && { type },
14078
- ...category && { category }
14079
- };
14080
- let query = { ...baseQuery };
14081
- const cacheOptions = {
14082
13991
  ...status && { status },
14083
13992
  ...type && { type },
14084
13993
  ...category && { category },
14085
- page: String(page),
14086
- limit: String(limit),
14087
- sort: JSON.stringify(sort)
13994
+ ...search && { $text: { search } }
14088
13995
  };
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
- }
13996
+ let query = { ...baseQuery };
14099
13997
  const escapeRegex = (input) => input.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
14100
13998
  const buildGroupedPipeline = (matchQuery) => [
14101
13999
  { $match: matchQuery },
@@ -14253,9 +14151,6 @@ function useVehicleRepo() {
14253
14151
  length = regexCountResult[0]?.total || 0;
14254
14152
  }
14255
14153
  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
14154
  return data;
14260
14155
  } catch (error) {
14261
14156
  throw error;
@@ -14267,14 +14162,6 @@ function useVehicleRepo() {
14267
14162
  } catch (error) {
14268
14163
  throw new import_node_server_utils70.BadRequestError("Invalid site ID format.");
14269
14164
  }
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
14165
  try {
14279
14166
  const categories = await collection.aggregate([
14280
14167
  { $match: { site } },
@@ -14294,17 +14181,6 @@ function useVehicleRepo() {
14294
14181
  },
14295
14182
  { $sort: { title: 1 } }
14296
14183
  ]).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
14184
  return categories;
14309
14185
  } catch (error) {
14310
14186
  if (error instanceof import_node_server_utils70.BadRequestError) {
@@ -14320,12 +14196,6 @@ function useVehicleRepo() {
14320
14196
  throw new import_node_server_utils70.BadRequestError("Invalid vehicle ID format.");
14321
14197
  }
14322
14198
  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
14199
  const data = await collection.aggregate([
14330
14200
  { $match: { _id } },
14331
14201
  { $limit: 1 },
@@ -14495,11 +14365,6 @@ function useVehicleRepo() {
14495
14365
  throw new import_node_server_utils70.NotFoundError("Vehicle not found.");
14496
14366
  }
14497
14367
  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
14368
  return result;
14504
14369
  } catch (error) {
14505
14370
  throw error;
@@ -14511,15 +14376,6 @@ function useVehicleRepo() {
14511
14376
  throw new import_node_server_utils70.BadRequestError(error.details[0].message);
14512
14377
  }
14513
14378
  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
14379
  const data = await collection.findOne({
14524
14380
  plateNumber: value,
14525
14381
  status: "active"
@@ -14527,11 +14383,6 @@ function useVehicleRepo() {
14527
14383
  if (!data) {
14528
14384
  throw new import_node_server_utils70.NotFoundError("Vehicle not found.");
14529
14385
  }
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
14386
  return data;
14536
14387
  } catch (error2) {
14537
14388
  throw error2;
@@ -14556,16 +14407,6 @@ function useVehicleRepo() {
14556
14407
  if (res.modifiedCount === 0) {
14557
14408
  throw new import_node_server_utils70.InternalServerError("Unable to update vehicle.");
14558
14409
  }
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
14410
  return res.modifiedCount;
14570
14411
  } catch (error) {
14571
14412
  throw error;
@@ -14589,16 +14430,6 @@ function useVehicleRepo() {
14589
14430
  );
14590
14431
  if (res.modifiedCount === 0)
14591
14432
  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
14433
  return res.modifiedCount;
14603
14434
  } catch (error) {
14604
14435
  throw error;
@@ -14609,25 +14440,11 @@ function useVehicleRepo() {
14609
14440
  if (error) {
14610
14441
  throw new import_node_server_utils70.BadRequestError(error.details[0].message);
14611
14442
  }
14612
- const cacheKey = (0, import_node_server_utils70.makeCacheKey)(vehicles_namespace_collection, {
14613
- plateNumber,
14614
- status: "active"
14615
- });
14616
14443
  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
14444
  const data = await collection.findOne(
14623
14445
  { plateNumber, status: "active" },
14624
14446
  { sort: { _id: -1 } }
14625
14447
  );
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
14448
  return data;
14632
14449
  } catch (error2) {
14633
14450
  throw new import_node_server_utils70.InternalServerError(
@@ -14651,19 +14468,6 @@ function useVehicleRepo() {
14651
14468
  nric: _nric
14652
14469
  };
14653
14470
  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
14471
  try {
14668
14472
  const items = await collection.aggregate([
14669
14473
  { $match: query },
@@ -14684,9 +14488,6 @@ function useVehicleRepo() {
14684
14488
  ]).toArray();
14685
14489
  const length = await collection.countDocuments(query);
14686
14490
  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
14491
  return data;
14691
14492
  } catch (error) {
14692
14493
  throw error;
@@ -14701,19 +14502,9 @@ function useVehicleRepo() {
14701
14502
  end: { $exists: true, $lte: now }
14702
14503
  // check only end
14703
14504
  },
14704
- { $set: { status: "deleted", deletedAt: now } },
14505
+ { $set: { status: "deleted", deletedAt: now, isDeletedInDahua: true } },
14705
14506
  { session }
14706
14507
  );
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
14508
  return res.modifiedCount;
14718
14509
  } catch (error) {
14719
14510
  throw error;
@@ -14732,21 +14523,6 @@ function useVehicleRepo() {
14732
14523
  const query = {
14733
14524
  unit
14734
14525
  };
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
14526
  const items = await collection.find(query, {
14751
14527
  projection: {
14752
14528
  createdAt: 0,
@@ -14759,14 +14535,24 @@ function useVehicleRepo() {
14759
14535
  }).toArray();
14760
14536
  const length = await collection.countDocuments(query);
14761
14537
  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
14538
  return data;
14766
14539
  } catch (error) {
14767
14540
  throw error;
14768
14541
  }
14769
14542
  }
14543
+ async function getAllExpiredVehicles() {
14544
+ try {
14545
+ const now = (/* @__PURE__ */ new Date()).toISOString();
14546
+ const query = {
14547
+ end: { $lte: now },
14548
+ status: { $ne: "deleted" }
14549
+ };
14550
+ const items = await collection.find(query).toArray();
14551
+ return items;
14552
+ } catch (error) {
14553
+ throw error;
14554
+ }
14555
+ }
14770
14556
  return {
14771
14557
  createIndex,
14772
14558
  createTextIndex,
@@ -14780,7 +14566,8 @@ function useVehicleRepo() {
14780
14566
  getVehicleByPlateNumber,
14781
14567
  getVehiclesByNRIC,
14782
14568
  deleteExpiredVehicles,
14783
- getAllVehiclesByUnitId
14569
+ getAllVehiclesByUnitId,
14570
+ getAllExpiredVehicles
14784
14571
  };
14785
14572
  }
14786
14573
 
@@ -15393,18 +15180,32 @@ function formatDahuaDate(date) {
15393
15180
  date.getSeconds()
15394
15181
  )}`;
15395
15182
  }
15183
+ function parseDahuaFind(text) {
15184
+ const found = Number(text.match(/found=(\d+)/)?.[1] || 0);
15185
+ if (!found) {
15186
+ return { exists: false };
15187
+ }
15188
+ return {
15189
+ exists: true,
15190
+ recNo: text.match(/records\[0\]\.RecNo=(.*)/)?.[1]?.trim(),
15191
+ plateNumber: text.match(/records\[0\]\.PlateNumber=(.*)/)?.[1]?.trim()
15192
+ };
15193
+ }
15396
15194
  function useVehicleService() {
15397
15195
  const {
15398
15196
  add: _add,
15399
15197
  deleteVehicle: _deleteVehicle,
15400
15198
  updateVehicleById: _updateVehicleById,
15401
15199
  getVehicleById: _getVehicleById,
15402
- deleteExpiredVehicles: _deleteExpiredVehicles
15200
+ deleteExpiredVehicles: _deleteExpiredVehicles,
15201
+ getVehicleByPlateNumber: _getVehicleByPlateNumber,
15202
+ getAllExpiredVehicles: _getAllExpiredVehicles
15403
15203
  } = useVehicleRepo();
15404
15204
  const {
15405
15205
  addPlateNumber: _addPlateNumber,
15406
15206
  removePlateNumber: _removePlateNumber,
15407
- updatePlateNumber: _updatePlateNumber
15207
+ updatePlateNumber: _updatePlateNumber,
15208
+ getPlateNumber: _getPlateNumber
15408
15209
  } = useDahuaService();
15409
15210
  const { getAllCameraWithPassword: _getAllSiteCameras } = useSiteCameraRepo();
15410
15211
  const { getById: _getById } = useOrgRepo();
@@ -15415,9 +15216,15 @@ function useVehicleService() {
15415
15216
  if (!session) {
15416
15217
  throw new Error("Unable to start session for vehicle service.");
15417
15218
  }
15418
- const org = await _getById(value.org);
15219
+ const [_vehiclePlateNumber] = value.plateNumber;
15220
+ const [existingPlateNumber, org] = await Promise.all([
15221
+ _getVehicleByPlateNumber(_vehiclePlateNumber),
15222
+ _getById(value.org)
15223
+ ]);
15419
15224
  if (!org)
15420
15225
  throw new import_node_server_utils72.BadRequestError("Org not found");
15226
+ if (existingPlateNumber)
15227
+ throw new import_node_server_utils72.BadRequestError("Vehicle plate number already exists");
15421
15228
  if (!Object.values(OrgNature).includes(org.nature)) {
15422
15229
  throw new import_node_server_utils72.BadRequestError(
15423
15230
  "This organization is not allowed to add vehicles."
@@ -15497,29 +15304,61 @@ function useVehicleService() {
15497
15304
  if (vehicleValue.status && vehicleValue.status !== "pending" /* PENDING */) {
15498
15305
  for (const camera of siteCameras) {
15499
15306
  const { host, username, password } = camera;
15500
- const dahuaPayload = {
15307
+ const plateNumber2 = vehicleValue.plateNumber;
15308
+ const dahuaQuery = {
15501
15309
  host,
15502
15310
  username,
15503
15311
  password,
15504
- plateNumber,
15505
- mode: _mode,
15506
- owner,
15507
- ...startDateDahua ? { start: startDateDahua } : {},
15508
- ...endDateDahua ? { end: endDateDahua } : {}
15312
+ plateNumber: plateNumber2,
15313
+ mode: _mode
15509
15314
  };
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
- );
15315
+ const raw = await _getPlateNumber(dahuaQuery);
15316
+ const parsed = parseDahuaFind(raw);
15317
+ if (!parsed.exists) {
15318
+ const dahuaPayload = {
15319
+ host,
15320
+ username,
15321
+ password,
15322
+ plateNumber: plateNumber2,
15323
+ mode: _mode,
15324
+ owner,
15325
+ ...startDateDahua ? { start: startDateDahua } : {},
15326
+ ...endDateDahua ? { end: endDateDahua } : {}
15327
+ };
15328
+ const dahuaResponse = await _addPlateNumber(dahuaPayload);
15329
+ if (dahuaResponse?.statusCode !== 200) {
15330
+ throw new import_node_server_utils72.BadRequestError(
15331
+ `Failed to add plate number to ANPR ${_type}`
15332
+ );
15333
+ }
15334
+ const responseData = dahuaResponse?.data?.toString("utf-8") ?? "";
15335
+ vehicleValue.recNo = responseData.split("=")[1]?.trim();
15336
+ } else {
15337
+ const dahuaPayload = {
15338
+ host,
15339
+ username,
15340
+ password,
15341
+ plateNumber: plateNumber2,
15342
+ recno: parsed.recNo,
15343
+ mode: _mode,
15344
+ ...startDateDahua ? { start: startDateDahua } : {},
15345
+ ...endDateDahua ? { end: endDateDahua } : {},
15346
+ owner,
15347
+ isOpenGate: true
15348
+ };
15349
+ const dahuaResponse = await _updatePlateNumber(dahuaPayload);
15350
+ if (dahuaResponse?.statusCode !== 200) {
15351
+ throw new import_node_server_utils72.BadRequestError(
15352
+ `Failed to update plate number to ANPR ${_type}`
15353
+ );
15354
+ }
15355
+ vehicleValue.recNo = parsed.recNo;
15515
15356
  }
15516
- const responseData = dahuaResponse?.data?.toString("utf-8") ?? "";
15517
- vehicleValue.recNo = responseData.split("=")[1]?.trim();
15518
15357
  if (value.peopleId && vehicleValue.recNo) {
15519
15358
  await _pushVehicleById(
15520
15359
  value.peopleId,
15521
15360
  {
15522
- plateNumber,
15361
+ plateNumber: plateNumber2,
15523
15362
  recNo: vehicleValue.recNo
15524
15363
  },
15525
15364
  session
@@ -15710,6 +15549,43 @@ function useVehicleService() {
15710
15549
  }
15711
15550
  try {
15712
15551
  session.startTransaction();
15552
+ const vehicles = await _getAllExpiredVehicles();
15553
+ let siteCameras = [];
15554
+ for (const vehicle of vehicles) {
15555
+ const site = vehicle.site;
15556
+ const recno = vehicle.recNo;
15557
+ let page = 1;
15558
+ let pages = 1;
15559
+ const limit = 20;
15560
+ do {
15561
+ const siteCameraReq = await _getAllSiteCameras({
15562
+ site,
15563
+ type: "anpr",
15564
+ direction: ["both", "entry"],
15565
+ page,
15566
+ limit
15567
+ });
15568
+ pages = siteCameraReq.pages || 1;
15569
+ siteCameras.push(...siteCameraReq.items);
15570
+ page++;
15571
+ } while (page < pages);
15572
+ if (!siteCameras.length) {
15573
+ throw new import_node_server_utils72.BadRequestError("No site cameras found.");
15574
+ }
15575
+ for (const camera of siteCameras) {
15576
+ const host = camera.host;
15577
+ const username = camera.username;
15578
+ const password = camera.password;
15579
+ const dahuaPayload = {
15580
+ host,
15581
+ username,
15582
+ password,
15583
+ recno,
15584
+ mode: "TrafficRedList" /* TRAFFIC_REDLIST */
15585
+ };
15586
+ await _removePlateNumber(dahuaPayload);
15587
+ }
15588
+ }
15713
15589
  await _deleteExpiredVehicles();
15714
15590
  await session.commitTransaction();
15715
15591
  return `Expired Vehicle plate numbers deleted successfully.`;
@@ -16100,21 +15976,21 @@ function useDahuaService() {
16100
15976
  org,
16101
15977
  status: "unregistered" /* UNREGISTERED */
16102
15978
  };
16103
- const typesForAutoRegister = [
16104
- "guest" /* GUEST */,
16105
- "resident" /* RESIDENT */,
16106
- "tenant" /* TENANT */
16107
- ];
15979
+ const typesForAutoRegister = Object.values(PersonTypes);
15980
+ let startDate = vehicle?.start ? new Date(vehicle?.start) : /* @__PURE__ */ new Date();
15981
+ let endDate = vehicle?.end ? new Date(vehicle?.end) : new Date(startDate.getTime() + 60 * 60 * 1e3);
16108
15982
  if (vehicle && typeof vehicle.category === "string" && typesForAutoRegister.includes(vehicle.category)) {
16109
15983
  visitorTransaction.name = vehicle.name;
16110
15984
  visitorTransaction.nric = vehicle.nric;
16111
15985
  visitorTransaction.contact = vehicle.phoneNumber;
16112
15986
  visitorTransaction.block = Number(vehicle.block);
16113
15987
  visitorTransaction.level = vehicle.level;
16114
- visitorTransaction.unit = vehicle.unit;
15988
+ visitorTransaction.unit = vehicle.unit?.toString();
16115
15989
  visitorTransaction.unitName = vehicle.unitName;
16116
15990
  visitorTransaction.type = vehicle.category;
16117
15991
  visitorTransaction.status = "registered" /* REGISTERED */;
15992
+ visitorTransaction.recNo = vehicle.recNo;
15993
+ visitorTransaction.expiredAt = vehicle.end;
16118
15994
  }
16119
15995
  const dahuaPayload = {
16120
15996
  host,
@@ -16124,13 +16000,15 @@ function useDahuaService() {
16124
16000
  mode: "TrafficRedList" /* TRAFFIC_REDLIST */,
16125
16001
  owner: vehicle?.name ?? ""
16126
16002
  };
16003
+ dahuaPayload.start = formatDahuaDate(startDate);
16004
+ dahuaPayload.end = formatDahuaDate(endDate);
16127
16005
  const shouldHaveTimeLimit = visitorTransaction.type === "guest" /* GUEST */ || visitorTransaction.status === "unregistered" /* UNREGISTERED */;
16128
16006
  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();
16007
+ const startDate2 = /* @__PURE__ */ new Date();
16008
+ const endDate2 = new Date(startDate2.getTime() + 60 * 60 * 1e3);
16009
+ dahuaPayload.start = formatDahuaDate(startDate2);
16010
+ dahuaPayload.end = formatDahuaDate(endDate2);
16011
+ visitorTransaction.expiredAt = endDate2.toISOString();
16134
16012
  }
16135
16013
  try {
16136
16014
  await addPlateNumber(dahuaPayload);
@@ -16379,14 +16257,14 @@ function useDahuaService() {
16379
16257
  start: import_joi39.default.string().isoDate().optional().allow("", null),
16380
16258
  end: import_joi39.default.string().isoDate().optional().allow("", null),
16381
16259
  owner: import_joi39.default.string().optional().allow("", null),
16382
- openGate: import_joi39.default.boolean().optional().allow(null)
16260
+ isOpenGate: import_joi39.default.boolean().optional().allow(null)
16383
16261
  });
16384
16262
  const { error } = validation.validate(value);
16385
16263
  if (error) {
16386
16264
  throw new import_node_server_utils73.BadRequestError(`Validation error: ${error.message}`);
16387
16265
  }
16388
16266
  value.owner = String(value.owner ?? "").substring(0, 15) || "unknown";
16389
- const _openGate = String(value.openGate);
16267
+ const _openGate = String(value.isOpenGate);
16390
16268
  const isOpenGateString = _openGate && _openGate !== "undefined" ? _openGate : "true";
16391
16269
  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
16270
  try {
@@ -16447,7 +16325,7 @@ function useDahuaService() {
16447
16325
  username: import_joi39.default.string().required(),
16448
16326
  password: import_joi39.default.string().required(),
16449
16327
  recno: import_joi39.default.string().required(),
16450
- mode: import_joi39.default.string().valid("TrafficBlackList", "TrafficRedList").required()
16328
+ mode: import_joi39.default.string().valid(...Object.values(ANPRMode)).required()
16451
16329
  });
16452
16330
  const { error } = validation.validate(value);
16453
16331
  if (error) {
@@ -16465,12 +16343,39 @@ function useDahuaService() {
16465
16343
  import_node_server_utils73.logger.error(`[${value.host}] Error removing plate number:`, error2);
16466
16344
  }
16467
16345
  }
16346
+ async function getPlateNumber(value) {
16347
+ const validation = import_joi39.default.object({
16348
+ host: import_joi39.default.string().required(),
16349
+ username: import_joi39.default.string().required(),
16350
+ password: import_joi39.default.string().required(),
16351
+ plateNumber: import_joi39.default.string().required(),
16352
+ mode: import_joi39.default.string().valid(...Object.values(ANPRMode)).required()
16353
+ });
16354
+ const { error } = validation.validate(value);
16355
+ if (error) {
16356
+ throw new import_node_server_utils73.BadRequestError(`Validation error: ${error.message}`);
16357
+ }
16358
+ try {
16359
+ const response = await useDahuaDigest({
16360
+ host: value.host,
16361
+ username: value.username,
16362
+ password: value.password,
16363
+ endpoint: `/cgi-bin/recordFinder.cgi?action=find&name=${value.mode}&condition.PlateNumber=${encodeURIComponent(value.plateNumber)}`
16364
+ });
16365
+ const text = response?.data?.toString?.("utf-8");
16366
+ return text;
16367
+ } catch (error2) {
16368
+ import_node_server_utils73.logger.error(`[${value.host}] Error finding plate number:`, error2);
16369
+ throw error2;
16370
+ }
16371
+ }
16468
16372
  return {
16469
16373
  getSnapshot,
16470
16374
  getTrafficJunction,
16471
16375
  addPlateNumber,
16472
16376
  removePlateNumber,
16473
- updatePlateNumber
16377
+ updatePlateNumber,
16378
+ getPlateNumber
16474
16379
  };
16475
16380
  }
16476
16381
 
@@ -20726,10 +20631,13 @@ function useVisitorTransactionService() {
20726
20631
  const { getSiteById: _getSiteById } = useSiteRepo();
20727
20632
  const {
20728
20633
  addPlateNumber: _addPlateNumber,
20729
- removePlateNumber: _removePlateNumber
20634
+ removePlateNumber: _removePlateNumber,
20635
+ getPlateNumber: _getPlateNumber,
20636
+ updatePlateNumber: _updatePlateNumber
20730
20637
  } = useDahuaService();
20731
20638
  const { getAllSites: _getAllSites } = useSiteRepo();
20732
20639
  const { getByUserId: _getByUserId } = usePersonRepo();
20640
+ const { add: addVehicle } = useVehicleRepo();
20733
20641
  async function add(value) {
20734
20642
  const session = import_node_server_utils100.useAtlas.getClient()?.startSession();
20735
20643
  const allowedPersonTypes = [
@@ -20746,12 +20654,12 @@ function useVisitorTransactionService() {
20746
20654
  let site;
20747
20655
  if (value.site) {
20748
20656
  [camera, site] = await Promise.all([
20749
- _getBySite(value.site, { type: "anpr" }),
20657
+ _getBySite(value.site, { type: "anpr" /* ANPR */ }),
20750
20658
  _getSiteById(value.site)
20751
20659
  ]);
20752
20660
  }
20753
- const minutesExpiration = site?.dahuaTimeExpiration ? site?.dahuaTimeExpiration : 60;
20754
- const end = value.checkOut ? new Date(value.checkOut) : new Date(start.getTime() + minutesExpiration * 60 * 1e3);
20661
+ const hourExpiration = site?.dahuaTimeExpiration ? site?.dahuaTimeExpiration : 24 * 60;
20662
+ const end = value.checkOut ? new Date(value.checkOut) : new Date(start.getTime() + hourExpiration * 60 * 1e3);
20755
20663
  const startString = start.toISOString();
20756
20664
  const endString = end.toISOString();
20757
20665
  const startDahuaDate = formatDahuaDate(start);
@@ -20827,27 +20735,76 @@ function useVisitorTransactionService() {
20827
20735
  }
20828
20736
  }
20829
20737
  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
20738
+ const host = camera.host;
20739
+ const username = camera.username;
20740
+ const password = camera.password;
20741
+ const mode = "TrafficRedList" /* TRAFFIC_REDLIST */;
20742
+ const _plateNumber = value.plateNumber;
20743
+ const dahuaQuery = {
20744
+ host,
20745
+ username,
20746
+ password,
20747
+ plateNumber: _plateNumber,
20748
+ mode
20840
20749
  };
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
- );
20750
+ const raw = await _getPlateNumber(dahuaQuery);
20751
+ const parsed = parseDahuaFind(raw);
20752
+ if (!parsed.exists) {
20753
+ const dahuaPayload = {
20754
+ host,
20755
+ username,
20756
+ password,
20757
+ plateNumber: _plateNumber,
20758
+ mode,
20759
+ start: startDahuaDate,
20760
+ end: endDahuaDate,
20761
+ owner: value.name ?? "",
20762
+ isOpenGate: site?.isOpenGate ?? true
20763
+ };
20764
+ const dahuaResponse = await _addPlateNumber(dahuaPayload);
20765
+ if (dahuaResponse?.statusCode !== 200) {
20766
+ throw new import_node_server_utils100.BadRequestError(
20767
+ `Failed to add plate number to ANPR whitelist`
20768
+ );
20769
+ }
20770
+ const responseData = dahuaResponse?.data?.toString("utf-8") ?? "";
20771
+ value.recNo = responseData.split("=")[1]?.trim();
20772
+ value.checkIn = startString;
20773
+ value.expiredAt = endString;
20774
+ const vehiclePayload = {
20775
+ name: value.name ?? "",
20776
+ category: value.type,
20777
+ org: value.org,
20778
+ site: value.site,
20779
+ plateNumber: value.plateNumber,
20780
+ type: "whitelist" /* WHITELIST */,
20781
+ nric: value.nric,
20782
+ start: startString,
20783
+ end: endString,
20784
+ recNo: value.recNo
20785
+ };
20786
+ await addVehicle(vehiclePayload);
20787
+ } else {
20788
+ const dahuaPayload = {
20789
+ host,
20790
+ username,
20791
+ password,
20792
+ plateNumber: _plateNumber,
20793
+ recno: parsed.recNo,
20794
+ mode,
20795
+ start: startDahuaDate,
20796
+ end: endDahuaDate,
20797
+ owner: value.name ?? "",
20798
+ isOpenGate: site?.isOpenGate ?? true
20799
+ };
20800
+ const dahuaResponse = await _updatePlateNumber(dahuaPayload);
20801
+ if (dahuaResponse?.statusCode !== 200) {
20802
+ throw new import_node_server_utils100.BadRequestError(
20803
+ `Failed to update plate number to ANPR ${"whitelist" /* WHITELIST */}`
20804
+ );
20805
+ }
20806
+ value.recNo = parsed.recNo;
20846
20807
  }
20847
- const responseData = dahuaResponse?.data?.toString("utf-8") ?? "";
20848
- value.recNo = responseData.split("=")[1]?.trim();
20849
- value.checkIn = startString;
20850
- value.expiredAt = endString;
20851
20808
  }
20852
20809
  const result = await _add(value, session);
20853
20810
  await session?.commitTransaction();
@@ -21181,7 +21138,6 @@ function useVisitorTransactionController() {
21181
21138
  }
21182
21139
  }
21183
21140
  async function inviteVisitor(req, res, next) {
21184
- const inviter = req.params.inviterId;
21185
21141
  const schema2 = import_joi55.default.object({
21186
21142
  name: import_joi55.default.string().required(),
21187
21143
  contact: import_joi55.default.string().required(),
@@ -38925,8 +38881,7 @@ function useOccurrenceEntryController() {
38925
38881
  getLatestSerialNumber: _getLatestSerialNumber
38926
38882
  } = useOccurrenceEntryRepo();
38927
38883
  async function add(req, res, next) {
38928
- const payload = { ...req.body };
38929
- const { error } = schemaOccurrenceEntry.validate(payload, {
38884
+ const { error, value } = schemaOccurrenceEntry.validate(req.body, {
38930
38885
  abortEarly: false
38931
38886
  });
38932
38887
  if (error) {
@@ -38936,7 +38891,7 @@ function useOccurrenceEntryController() {
38936
38891
  return;
38937
38892
  }
38938
38893
  try {
38939
- const data = await _add(payload);
38894
+ const data = await _add(value);
38940
38895
  res.status(201).json(data);
38941
38896
  return;
38942
38897
  } catch (error2) {
@@ -39018,9 +38973,8 @@ function useOccurrenceEntryController() {
39018
38973
  }
39019
38974
  }
39020
38975
  async function updateOccurrenceEntryById(req, res, next) {
39021
- const _id = req.params.id;
39022
- const payload = { _id, ...req.body };
39023
- const { error } = schemaUpdateOccurrenceEntry.validate(payload, {
38976
+ const payload = { _id: req.params.id, ...req.body };
38977
+ const { error, value } = schemaUpdateOccurrenceEntry.validate(payload, {
39024
38978
  abortEarly: false
39025
38979
  });
39026
38980
  if (error) {
@@ -39029,8 +38983,9 @@ function useOccurrenceEntryController() {
39029
38983
  next(new import_node_server_utils184.BadRequestError(messages));
39030
38984
  return;
39031
38985
  }
38986
+ const { _id, ...rest } = value;
39032
38987
  try {
39033
- const result = await _updateOccurrenceEntryById(_id, req.body);
38988
+ const result = await _updateOccurrenceEntryById(_id, rest);
39034
38989
  res.status(200).json({ message: result });
39035
38990
  return;
39036
38991
  } catch (error2) {
@@ -45248,12 +45203,6 @@ function useVerificationRepoV2() {
45248
45203
  err
45249
45204
  );
45250
45205
  });
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
45206
  return result;
45258
45207
  } catch (error) {
45259
45208
  throw new import_node_server_utils217.InternalServerError("Error updating verification status.");
@@ -45659,9 +45608,12 @@ function useVerificationControllerV2() {
45659
45608
  async function verify(req, res, next) {
45660
45609
  try {
45661
45610
  const schema2 = import_joi126.default.object({ verificationCode: import_joi126.default.string().required() });
45662
- const { error, value } = schema2.validate({
45663
- verificationCode: req.params.verificationCode
45664
- });
45611
+ const { error, value } = schema2.validate(
45612
+ {
45613
+ verificationCode: req.params.verificationCode
45614
+ },
45615
+ { abortEarly: false }
45616
+ );
45665
45617
  if (error) {
45666
45618
  const messages = error.details.map((d) => d.message).join(", ");
45667
45619
  import_node_server_utils219.logger.log({ level: "error", message: messages });
@@ -45687,7 +45639,7 @@ function useVerificationControllerV2() {
45687
45639
  siteId: import_joi126.default.string().hex().length(24).optional().allow("", null),
45688
45640
  siteName: import_joi126.default.string().optional().allow("", null)
45689
45641
  });
45690
- const { error, value } = schema2.validate(req.body);
45642
+ const { error, value } = schema2.validate(req.body, { abortEarly: false });
45691
45643
  if (error) {
45692
45644
  const messages = error.details.map((d) => d.message).join(", ");
45693
45645
  import_node_server_utils219.logger.log({ level: "error", message: messages });
@@ -45722,7 +45674,7 @@ function useVerificationControllerV2() {
45722
45674
  siteId: import_joi126.default.string().hex().length(24).required(),
45723
45675
  siteName: import_joi126.default.string().required()
45724
45676
  });
45725
- const { error, value } = schema2.validate(req.body);
45677
+ const { error, value } = schema2.validate(req.body, { abortEarly: false });
45726
45678
  if (error) {
45727
45679
  const messages = error.details.map((d) => d.message).join(", ");
45728
45680
  import_node_server_utils219.logger.log({ level: "error", message: messages });
@@ -45748,7 +45700,7 @@ function useVerificationControllerV2() {
45748
45700
  const schema2 = import_joi126.default.object({
45749
45701
  email: import_joi126.default.string().email().lowercase().required()
45750
45702
  });
45751
- const { error, value } = schema2.validate(req.body);
45703
+ const { error, value } = schema2.validate(req.body, { abortEarly: false });
45752
45704
  if (error) {
45753
45705
  const messages = error.details.map((d) => d.message).join(", ");
45754
45706
  import_node_server_utils219.logger.log({ level: "error", message: messages });
@@ -45778,13 +45730,14 @@ function useVerificationControllerV2() {
45778
45730
 
45779
45731
  // src/controllers/auth-v2.controller.ts
45780
45732
  var import_joi127 = __toESM(require("joi"));
45781
- var import_node_server_utils222 = require("@7365admin1/node-server-utils");
45733
+ var import_node_server_utils223 = require("@7365admin1/node-server-utils");
45782
45734
 
45783
45735
  // src/services/auth-v2.service.ts
45784
45736
  var import_node_server_utils221 = require("@7365admin1/node-server-utils");
45785
45737
  var import_uuid2 = require("uuid");
45786
45738
 
45787
45739
  // src/repositories/user-v2.repo.ts
45740
+ var import_mongodb123 = require("mongodb");
45788
45741
  var import_node_server_utils220 = require("@7365admin1/node-server-utils");
45789
45742
  function useUserRepoV2() {
45790
45743
  const { updateFeedbackCreatedByName } = useFeedbackRepo();
@@ -45796,6 +45749,7 @@ function useUserRepoV2() {
45796
45749
  }
45797
45750
  const namespace_collection = "users";
45798
45751
  const collection = db.collection(namespace_collection);
45752
+ const { delNamespace, setCache, getCache, delCache } = (0, import_node_server_utils220.useCache)(namespace_collection);
45799
45753
  async function createIndex() {
45800
45754
  try {
45801
45755
  await collection.createIndexes([{ key: { email: 1 } }]);
@@ -45805,10 +45759,7 @@ function useUserRepoV2() {
45805
45759
  }
45806
45760
  async function createTextIndex() {
45807
45761
  try {
45808
- await collection.createIndex({
45809
- name: "text",
45810
- email: "text"
45811
- });
45762
+ await collection.createIndex({ name: "text", email: "text" });
45812
45763
  } catch (error) {
45813
45764
  throw new import_node_server_utils220.InternalServerError("Failed to create text index on user.");
45814
45765
  }
@@ -45823,24 +45774,22 @@ function useUserRepoV2() {
45823
45774
  throw new import_node_server_utils220.InternalServerError("Failed to create unique index on user.");
45824
45775
  }
45825
45776
  }
45826
- const { delNamespace, setCache, getCache, delCache } = (0, import_node_server_utils220.useCache)(namespace_collection);
45827
45777
  async function createUser(value, session) {
45828
45778
  try {
45829
45779
  value = MUser(value);
45830
45780
  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(
45781
+ delNamespace().then(
45782
+ () => import_node_server_utils220.logger.info(`Cache cleared for namespace: ${namespace_collection}`)
45783
+ ).catch(
45784
+ (err) => import_node_server_utils220.logger.error(
45835
45785
  `Failed to clear cache for namespace: ${namespace_collection}`,
45836
45786
  err
45837
- );
45838
- });
45787
+ )
45788
+ );
45839
45789
  return res.insertedId;
45840
45790
  } catch (error) {
45841
45791
  import_node_server_utils220.logger.log({ level: "error", message: `${error}` });
45842
- const isDuplicated = error.message.includes("duplicate");
45843
- if (isDuplicated) {
45792
+ if (error.message.includes("duplicate")) {
45844
45793
  throw new import_node_server_utils220.BadRequestError("User already exists.");
45845
45794
  }
45846
45795
  throw error;
@@ -45857,11 +45806,9 @@ function useUserRepoV2() {
45857
45806
  const data = await collection.findOne({
45858
45807
  email: { $regex: `^${email}$`, $options: "i" }
45859
45808
  });
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
- });
45809
+ setCache(cacheKey, data, 15 * 60).then(() => import_node_server_utils220.logger.info(`Cache set for key: ${cacheKey}`)).catch(
45810
+ (err) => import_node_server_utils220.logger.error(`Failed to set cache for key: ${cacheKey}`, err)
45811
+ );
45865
45812
  return data;
45866
45813
  } catch (error) {
45867
45814
  throw new import_node_server_utils220.InternalServerError("Failed to get user by email.");
@@ -45869,26 +45816,22 @@ function useUserRepoV2() {
45869
45816
  }
45870
45817
  async function getUserByEmailStatus(email) {
45871
45818
  try {
45872
- const cacheOptions = {
45819
+ const cacheKey = (0, import_node_server_utils220.makeCacheKey)(namespace_collection, {
45873
45820
  email,
45874
45821
  status: "complete" /* COMPLETE */
45875
- };
45876
- const cacheKey = (0, import_node_server_utils220.makeCacheKey)(namespace_collection, cacheOptions);
45822
+ });
45877
45823
  const cachedData = await getCache(cacheKey);
45878
45824
  if (cachedData) {
45879
45825
  import_node_server_utils220.logger.info(`Cache hit for key: ${cacheKey}`);
45880
45826
  return cachedData;
45881
45827
  }
45882
- const query = {
45828
+ const data = await collection.findOne({
45883
45829
  email: { $regex: `^${email}$`, $options: "i" },
45884
45830
  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
45831
  });
45832
+ setCache(cacheKey, data, 15 * 60).then(() => import_node_server_utils220.logger.info(`Cache set for key: ${cacheKey}`)).catch(
45833
+ (err) => import_node_server_utils220.logger.error(`Failed to set cache for key: ${cacheKey}`, err)
45834
+ );
45892
45835
  return data;
45893
45836
  } catch (error) {
45894
45837
  throw new import_node_server_utils220.InternalServerError("Failed to get user by email.");
@@ -45911,17 +45854,10 @@ function useUserRepoV2() {
45911
45854
  let: { userOrgId: "$defaultOrg" },
45912
45855
  pipeline: [
45913
45856
  {
45914
- $match: {
45915
- $expr: { $eq: ["$orgId", "$$userOrgId"] }
45916
- }
45857
+ $match: { $expr: { $eq: ["$orgId", "$$userOrgId"] } }
45917
45858
  },
45918
45859
  {
45919
- $project: {
45920
- _id: 1,
45921
- name: 1,
45922
- type: 1,
45923
- siteId: 1
45924
- }
45860
+ $project: { _id: 1, name: 1, type: 1, siteId: 1 }
45925
45861
  }
45926
45862
  ],
45927
45863
  as: "serviceProviders"
@@ -45929,9 +45865,117 @@ function useUserRepoV2() {
45929
45865
  }
45930
45866
  ]).toArray();
45931
45867
  const data = results.length > 0 ? results[0] : null;
45932
- if (!data) {
45868
+ if (!data)
45933
45869
  throw new import_node_server_utils220.NotFoundError("User not found.");
45870
+ setCache(cacheKey, data, 15 * 60).then(() => import_node_server_utils220.logger.info(`Cache set for key: ${cacheKey}`)).catch(
45871
+ (err) => import_node_server_utils220.logger.error(`Failed to set cache for key: ${cacheKey}`, err)
45872
+ );
45873
+ return data;
45874
+ } catch (error) {
45875
+ if (error instanceof import_node_server_utils220.AppError)
45876
+ throw error;
45877
+ throw new import_node_server_utils220.InternalServerError("Failed to get user by id.");
45878
+ }
45879
+ }
45880
+ async function getUserByReferralCode(referralCode) {
45881
+ try {
45882
+ const cacheKey = (0, import_node_server_utils220.makeCacheKey)(namespace_collection, { referralCode });
45883
+ const cachedData = await getCache(cacheKey);
45884
+ if (cachedData) {
45885
+ import_node_server_utils220.logger.info(`Cache hit for key: ${cacheKey}`);
45886
+ return cachedData;
45887
+ }
45888
+ const data = await collection.findOne({ referralCode });
45889
+ setCache(cacheKey, data, 15 * 60).then(() => import_node_server_utils220.logger.info(`Cache set for key: ${cacheKey}`)).catch(
45890
+ (err) => import_node_server_utils220.logger.error(`Failed to set cache for key: ${cacheKey}`, err)
45891
+ );
45892
+ return data;
45893
+ } catch (error) {
45894
+ throw new import_node_server_utils220.InternalServerError("Failed to get user by referral code.");
45895
+ }
45896
+ }
45897
+ async function getByEmailApp(email, app) {
45898
+ try {
45899
+ const cacheKey = (0, import_node_server_utils220.makeCacheKey)(namespace_collection, { email, app });
45900
+ const cachedData = await getCache(cacheKey);
45901
+ if (cachedData) {
45902
+ import_node_server_utils220.logger.info(`Cache hit for key: ${cacheKey}`);
45903
+ return cachedData;
45934
45904
  }
45905
+ const data = await collection.findOne({
45906
+ email,
45907
+ "roles.app": app
45908
+ });
45909
+ setCache(cacheKey, data, 15 * 60).then(() => import_node_server_utils220.logger.info(`Cache set for key: ${cacheKey}`)).catch(
45910
+ (err) => import_node_server_utils220.logger.error(`Failed to set cache for key: ${cacheKey}`, err)
45911
+ );
45912
+ return data;
45913
+ } catch (error) {
45914
+ throw new import_node_server_utils220.InternalServerError("Failed to get user by email and app.");
45915
+ }
45916
+ }
45917
+ async function getUsersByOrgId({
45918
+ organization = "",
45919
+ search = "",
45920
+ page = 1,
45921
+ limit = 10,
45922
+ sort = {},
45923
+ type = "",
45924
+ status = "active"
45925
+ }) {
45926
+ page = page > 0 ? page - 1 : 0;
45927
+ const query = { status };
45928
+ const cacheOptions = { status };
45929
+ sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
45930
+ cacheOptions.sort = JSON.stringify(sort);
45931
+ if (search) {
45932
+ query.$text = { $search: search };
45933
+ cacheOptions.search = search;
45934
+ }
45935
+ if (type) {
45936
+ query.type = type;
45937
+ cacheOptions.type = type;
45938
+ }
45939
+ if (organization) {
45940
+ try {
45941
+ query.defaultOrg = new import_mongodb123.ObjectId(organization);
45942
+ cacheOptions.organization = organization.toString();
45943
+ } catch (error) {
45944
+ throw new import_node_server_utils220.BadRequestError("Invalid organization ID format.");
45945
+ }
45946
+ }
45947
+ delNamespace().then(() => {
45948
+ import_node_server_utils220.logger.info(`Cache cleared for namespace: ${namespace_collection}`);
45949
+ }).catch((err) => {
45950
+ import_node_server_utils220.logger.error(
45951
+ `Failed to clear cache for namespace: ${namespace_collection}`,
45952
+ err
45953
+ );
45954
+ });
45955
+ const cacheKey = (0, import_node_server_utils220.makeCacheKey)(namespace_collection, cacheOptions);
45956
+ const cachedData = await getCache(cacheKey);
45957
+ if (cachedData) {
45958
+ import_node_server_utils220.logger.info(`Cache hit for key: ${cacheKey}`);
45959
+ return cachedData;
45960
+ }
45961
+ try {
45962
+ const items = await collection.aggregate([
45963
+ { $match: query },
45964
+ { $sort: sort },
45965
+ { $skip: page * limit },
45966
+ { $limit: limit },
45967
+ {
45968
+ $project: {
45969
+ _id: 1,
45970
+ name: 1,
45971
+ email: 1,
45972
+ type: 1,
45973
+ status: 1
45974
+ }
45975
+ }
45976
+ ]).toArray();
45977
+ const length = await collection.countDocuments(query);
45978
+ const data = (0, import_node_server_utils220.paginate)(items, page, limit, length);
45935
45979
  setCache(cacheKey, data, 15 * 60).then(() => {
45936
45980
  import_node_server_utils220.logger.info(`Cache set for key: ${cacheKey}`);
45937
45981
  }).catch((err) => {
@@ -45939,12 +45983,197 @@ function useUserRepoV2() {
45939
45983
  });
45940
45984
  return data;
45941
45985
  } catch (error) {
45942
- if (error instanceof import_node_server_utils220.AppError) {
45986
+ import_node_server_utils220.logger.log({ level: "error", message: `${error}` });
45987
+ throw error;
45988
+ }
45989
+ }
45990
+ async function getUsers({
45991
+ search = "",
45992
+ page = 1,
45993
+ limit = 10,
45994
+ sort = {},
45995
+ type = "",
45996
+ status = "active"
45997
+ }) {
45998
+ page = page > 0 ? page - 1 : 0;
45999
+ const query = { status };
46000
+ const cacheOptions = { status };
46001
+ sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
46002
+ cacheOptions.sort = JSON.stringify(sort);
46003
+ if (search) {
46004
+ query.$text = { $search: search };
46005
+ cacheOptions.search = search;
46006
+ }
46007
+ if (type) {
46008
+ query.type = type;
46009
+ cacheOptions.type = type;
46010
+ }
46011
+ delNamespace().then(
46012
+ () => import_node_server_utils220.logger.info(`Cache cleared for namespace: ${namespace_collection}`)
46013
+ ).catch(
46014
+ (err) => import_node_server_utils220.logger.error(
46015
+ `Failed to clear cache for namespace: ${namespace_collection}`,
46016
+ err
46017
+ )
46018
+ );
46019
+ const cacheKey = (0, import_node_server_utils220.makeCacheKey)(namespace_collection, cacheOptions);
46020
+ const cachedData = await getCache(cacheKey);
46021
+ if (cachedData) {
46022
+ import_node_server_utils220.logger.info(`Cache hit for key: ${cacheKey}`);
46023
+ return cachedData;
46024
+ }
46025
+ try {
46026
+ const items = await collection.aggregate([
46027
+ { $match: query },
46028
+ { $sort: sort },
46029
+ { $skip: page * limit },
46030
+ { $limit: limit },
46031
+ { $project: { _id: 1, name: 1, email: 1, type: 1, status: 1 } }
46032
+ ]).toArray();
46033
+ const length = await collection.countDocuments(query);
46034
+ const data = (0, import_node_server_utils220.paginate)(items, page, limit, length);
46035
+ setCache(cacheKey, data, 15 * 60).then(() => import_node_server_utils220.logger.info(`Cache set for key: ${cacheKey}`)).catch(
46036
+ (err) => import_node_server_utils220.logger.error(`Failed to set cache for key: ${cacheKey}`, err)
46037
+ );
46038
+ return data;
46039
+ } catch (error) {
46040
+ import_node_server_utils220.logger.log({ level: "error", message: `${error}` });
46041
+ throw error;
46042
+ }
46043
+ }
46044
+ async function updatePasswordById({ _id, password }, session) {
46045
+ const cacheKey = (0, import_node_server_utils220.makeCacheKey)(namespace_collection, { _id });
46046
+ _id = (0, import_node_server_utils220.toObjectId)(_id);
46047
+ try {
46048
+ const result = await collection.updateOne(
46049
+ { _id },
46050
+ { $set: { password, updatedAt: (/* @__PURE__ */ new Date()).toISOString() } },
46051
+ { session }
46052
+ );
46053
+ delCache(cacheKey).then(() => {
46054
+ import_node_server_utils220.logger.info(`Cache deleted for key: ${cacheKey}`);
46055
+ }).catch((err) => {
46056
+ import_node_server_utils220.logger.error(`Failed to delete cache for key: ${cacheKey}`, err);
46057
+ });
46058
+ return result;
46059
+ } catch (error) {
46060
+ throw new import_node_server_utils220.InternalServerError("Failed to update user password.");
46061
+ }
46062
+ }
46063
+ async function updateUserFieldById({ _id, field, value } = {}, session) {
46064
+ const allowedFields = [
46065
+ "name",
46066
+ "email",
46067
+ "contact",
46068
+ "nric",
46069
+ "dateOfBirth",
46070
+ "profile",
46071
+ "gender",
46072
+ "defaultOrg"
46073
+ ];
46074
+ if (!allowedFields.includes(field)) {
46075
+ throw new import_node_server_utils220.BadRequestError(
46076
+ `Field "${field}" is not allowed to be updated.`
46077
+ );
46078
+ }
46079
+ try {
46080
+ _id = new import_mongodb123.ObjectId(_id);
46081
+ } catch (error) {
46082
+ throw new import_node_server_utils220.BadRequestError("Invalid ID.");
46083
+ }
46084
+ if (field === "defaultOrg") {
46085
+ try {
46086
+ value = new import_mongodb123.ObjectId(value);
46087
+ } catch (error) {
46088
+ throw new import_node_server_utils220.BadRequestError("Invalid organization ID.");
46089
+ }
46090
+ }
46091
+ if (field === "name") {
46092
+ try {
46093
+ await Promise.all([
46094
+ updateFeedbackCreatedByName(_id, value, session),
46095
+ updateWorkOrderCreatedByName(_id, value, session),
46096
+ updateUserNameBySignatureId(_id, value, session)
46097
+ ]);
46098
+ } catch (error) {
45943
46099
  throw error;
45944
- } else {
45945
- throw new import_node_server_utils220.InternalServerError("Failed to get user by email.");
45946
46100
  }
45947
46101
  }
46102
+ try {
46103
+ await collection.updateOne(
46104
+ { _id },
46105
+ { $set: { [field]: value, updatedAt: (/* @__PURE__ */ new Date()).toISOString() } },
46106
+ // Dynamically set the field
46107
+ { session }
46108
+ );
46109
+ const cacheKey = (0, import_node_server_utils220.makeCacheKey)(namespace_collection, { _id });
46110
+ delCache(cacheKey).then(() => {
46111
+ import_node_server_utils220.logger.info(`Cache deleted for key: ${cacheKey}`);
46112
+ }).catch((err) => {
46113
+ import_node_server_utils220.logger.error(`Failed to delete cache for key: ${cacheKey}`, err);
46114
+ });
46115
+ return `Successfully updated user ${field}.`;
46116
+ } catch (error) {
46117
+ throw new import_node_server_utils220.InternalServerError(`Failed to update user ${field}.`);
46118
+ }
46119
+ }
46120
+ async function updateBirthday({
46121
+ _id,
46122
+ month,
46123
+ day,
46124
+ year
46125
+ }, session) {
46126
+ try {
46127
+ _id = new import_mongodb123.ObjectId(_id);
46128
+ } catch (error) {
46129
+ throw new import_node_server_utils220.BadRequestError("Invalid user ID format.");
46130
+ }
46131
+ try {
46132
+ await collection.updateOne(
46133
+ { _id },
46134
+ {
46135
+ $set: {
46136
+ birthMonth: month,
46137
+ birthDay: day,
46138
+ birthYear: year,
46139
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
46140
+ }
46141
+ },
46142
+ { session }
46143
+ );
46144
+ const cacheKey = (0, import_node_server_utils220.makeCacheKey)(namespace_collection, { _id });
46145
+ delCache(cacheKey).then(() => {
46146
+ import_node_server_utils220.logger.info(`Cache deleted for key: ${cacheKey}`);
46147
+ }).catch((err) => {
46148
+ import_node_server_utils220.logger.error(`Failed to delete cache for key: ${cacheKey}`, err);
46149
+ });
46150
+ return "Successfully updated user birthday.";
46151
+ } catch (error) {
46152
+ throw new import_node_server_utils220.InternalServerError("Failed to update user birthday.");
46153
+ }
46154
+ }
46155
+ async function updatePassword({ _id, password }, session) {
46156
+ try {
46157
+ _id = new import_mongodb123.ObjectId(_id);
46158
+ } catch (error) {
46159
+ throw new import_node_server_utils220.BadRequestError("Invalid user ID format.");
46160
+ }
46161
+ try {
46162
+ const result = await collection.updateOne(
46163
+ { _id },
46164
+ { $set: { password, updatedAt: (/* @__PURE__ */ new Date()).toISOString() } },
46165
+ { session }
46166
+ );
46167
+ const cacheKey = (0, import_node_server_utils220.makeCacheKey)(namespace_collection, { _id });
46168
+ delCache(cacheKey).then(() => {
46169
+ import_node_server_utils220.logger.info(`Cache deleted for key: ${cacheKey}`);
46170
+ }).catch((err) => {
46171
+ import_node_server_utils220.logger.error(`Failed to delete cache for key: ${cacheKey}`, err);
46172
+ });
46173
+ return result;
46174
+ } catch (error) {
46175
+ throw new import_node_server_utils220.InternalServerError("Failed to update user password.");
46176
+ }
45948
46177
  }
45949
46178
  return {
45950
46179
  createIndex,
@@ -45953,7 +46182,13 @@ function useUserRepoV2() {
45953
46182
  createUser,
45954
46183
  getUserByEmail,
45955
46184
  getUserByEmailStatus,
45956
- getUserById
46185
+ getUserById,
46186
+ getUsers,
46187
+ getUsersByOrgId,
46188
+ updatePasswordById,
46189
+ updateUserFieldById,
46190
+ updateBirthday,
46191
+ updatePassword
45957
46192
  };
45958
46193
  }
45959
46194
 
@@ -46020,10 +46255,212 @@ function useAuthServiceV2() {
46020
46255
  };
46021
46256
  }
46022
46257
 
46258
+ // src/services/user-v2.service.ts
46259
+ var import_node_server_utils222 = require("@7365admin1/node-server-utils");
46260
+ var import_multer2 = require("multer");
46261
+ function useUserServiceV2() {
46262
+ const {
46263
+ createUser: _createUser,
46264
+ getUserByEmail: _getUserByEmail,
46265
+ updatePasswordById: _updatePasswordById,
46266
+ updateUserFieldById: _updateUserFieldById,
46267
+ getUserById,
46268
+ updatePassword
46269
+ } = useUserRepoV2();
46270
+ const { getRoleByName, addRole } = useRoleRepo();
46271
+ const { add: addMember } = useMemberRepo();
46272
+ const { getById: getOrgById } = useOrgRepo();
46273
+ const { getSiteById } = useSiteRepo();
46274
+ const {
46275
+ getVerificationById: _getVerificationById,
46276
+ updateVerificationStatusById: _updateVerificationStatusById
46277
+ } = useVerificationRepoV2();
46278
+ const { verify: _verify } = useVerificationServiceV2();
46279
+ const { createFile, deleteFileById } = useFileRepo();
46280
+ async function createUserBySignUp({
46281
+ id = "",
46282
+ name = ""
46283
+ }) {
46284
+ const session = import_node_server_utils222.useAtlas.getClient()?.startSession();
46285
+ session?.startTransaction();
46286
+ try {
46287
+ const signUp = await _getVerificationById(id);
46288
+ if (!signUp)
46289
+ throw new import_node_server_utils222.BadRequestError("Invalid sign up link.");
46290
+ if (signUp.status === "complete" /* COMPLETE */)
46291
+ throw new import_node_server_utils222.BadRequestError(
46292
+ "You have already an account created using this link."
46293
+ );
46294
+ const expired = signUp.expireAt < (/* @__PURE__ */ new Date()).toISOString();
46295
+ if (signUp.status === "expired" || expired)
46296
+ throw new import_node_server_utils222.BadRequestError("Sign up link expired.");
46297
+ const email = signUp.email;
46298
+ const _user = await _getUserByEmail(email);
46299
+ if (_user)
46300
+ throw new import_node_server_utils222.BadRequestError(`User already exists: ${email}.`);
46301
+ let org = null;
46302
+ if (signUp.metadata?.org) {
46303
+ org = await getOrgById(signUp.metadata.org);
46304
+ if (!org)
46305
+ signUp.metadata.org = "";
46306
+ }
46307
+ if (signUp.metadata?.siteId)
46308
+ await getSiteById(signUp.metadata?.siteId);
46309
+ const user = {
46310
+ email,
46311
+ password: signUp.metadata?.password,
46312
+ name,
46313
+ defaultOrg: org?._id?.toString() || ""
46314
+ };
46315
+ const userId = await _createUser(user, session);
46316
+ if (org?._id) {
46317
+ await addMember(
46318
+ {
46319
+ org: org?._id?.toString() || "",
46320
+ orgName: org?.name || "",
46321
+ user: userId.toString(),
46322
+ name,
46323
+ role: signUp.metadata?.role?.toString() || "",
46324
+ type: signUp.metadata?.app ?? "organization",
46325
+ siteId: signUp.metadata?.siteId?.toString() || "",
46326
+ siteName: signUp.metadata?.siteName || ""
46327
+ },
46328
+ session
46329
+ );
46330
+ }
46331
+ await _updateVerificationStatusById(
46332
+ id,
46333
+ "complete" /* COMPLETE */,
46334
+ session
46335
+ );
46336
+ await session?.commitTransaction();
46337
+ return userId;
46338
+ } catch (error) {
46339
+ await session?.abortTransaction();
46340
+ throw error;
46341
+ } finally {
46342
+ session?.endSession();
46343
+ }
46344
+ }
46345
+ async function resetPassword(id, newPassword, passwordConfirmation) {
46346
+ if (newPassword !== passwordConfirmation) {
46347
+ throw new import_node_server_utils222.BadRequestError("Passwords do not match.");
46348
+ }
46349
+ let hashedPassword;
46350
+ const session = import_node_server_utils222.useAtlas.getClient()?.startSession();
46351
+ session?.startTransaction();
46352
+ try {
46353
+ hashedPassword = await (0, import_node_server_utils222.hashPassword)(newPassword);
46354
+ } catch (error) {
46355
+ throw new import_node_server_utils222.InternalServerError(`Error hashing password: ${error}`);
46356
+ }
46357
+ try {
46358
+ const otpDoc = await _getVerificationById(id);
46359
+ if (!otpDoc) {
46360
+ throw new import_node_server_utils222.NotFoundError("You are using an invalid reset link.");
46361
+ }
46362
+ if (otpDoc.status === "complete" /* COMPLETE */) {
46363
+ throw new import_node_server_utils222.BadRequestError("This link has already been invalidated.");
46364
+ }
46365
+ const user = await _getUserByEmail(otpDoc.email);
46366
+ if (!user) {
46367
+ throw new import_node_server_utils222.NotFoundError("User not found.");
46368
+ }
46369
+ if (!user._id) {
46370
+ throw new import_node_server_utils222.InternalServerError("Invalid user ID.");
46371
+ }
46372
+ await Promise.all([
46373
+ _updateVerificationStatusById(id, "complete" /* COMPLETE */, session),
46374
+ _updatePasswordById(
46375
+ { _id: user._id.toString(), password: hashedPassword },
46376
+ session
46377
+ )
46378
+ ]);
46379
+ await session?.commitTransaction();
46380
+ return "Successfully reset password.";
46381
+ } catch (error) {
46382
+ await session?.abortTransaction();
46383
+ throw error;
46384
+ } finally {
46385
+ session?.endSession();
46386
+ }
46387
+ }
46388
+ const s3 = new import_node_server_utils222.useS3({
46389
+ accessKeyId: SPACES_ACCESS_KEY,
46390
+ secretAccessKey: SPACES_SECRET_KEY,
46391
+ endpoint: SPACES_ENDPOINT,
46392
+ region: SPACES_REGION,
46393
+ bucket: SPACES_BUCKET,
46394
+ forcePathStyle: false
46395
+ });
46396
+ async function updateUserProfile({
46397
+ file,
46398
+ user,
46399
+ previousProfile
46400
+ }) {
46401
+ const session = import_node_server_utils222.useAtlas.getClient()?.startSession();
46402
+ session?.startTransaction();
46403
+ const _file = {
46404
+ name: file.originalname,
46405
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
46406
+ };
46407
+ try {
46408
+ const id = await createFile(_file, session);
46409
+ await s3.uploadObject({
46410
+ key: id,
46411
+ body: file.buffer,
46412
+ contentType: file.mimetype
46413
+ });
46414
+ if (previousProfile) {
46415
+ await deleteFileById(previousProfile, session);
46416
+ await s3.deleteObject(previousProfile);
46417
+ }
46418
+ await _updateUserFieldById(
46419
+ { _id: user, field: "profile", value: id },
46420
+ session
46421
+ );
46422
+ await session?.commitTransaction();
46423
+ return id;
46424
+ } catch (error) {
46425
+ await session?.abortTransaction();
46426
+ throw error;
46427
+ } finally {
46428
+ session?.endSession();
46429
+ }
46430
+ }
46431
+ async function updatePasswordById(id, currentPassword, newPassword, passwordConfirmation) {
46432
+ let hashedPassword;
46433
+ const user = await getUserById(id);
46434
+ const isPasswordValid = await (0, import_node_server_utils222.comparePassword)(
46435
+ currentPassword,
46436
+ user.password
46437
+ );
46438
+ if (!isPasswordValid)
46439
+ throw new import_node_server_utils222.BadRequestError("Invalid current password.");
46440
+ if (newPassword !== passwordConfirmation)
46441
+ throw new import_node_server_utils222.BadRequestError("Passwords do not match.");
46442
+ try {
46443
+ hashedPassword = await (0, import_node_server_utils222.hashPassword)(newPassword);
46444
+ if (!hashedPassword)
46445
+ throw new import_node_server_utils222.InternalServerError("Error hashing password.");
46446
+ return await updatePassword({ _id: id, password: hashedPassword });
46447
+ } catch (error) {
46448
+ throw error;
46449
+ }
46450
+ }
46451
+ return {
46452
+ createUserBySignUp,
46453
+ resetPassword,
46454
+ updateUserProfile,
46455
+ updatePasswordById
46456
+ };
46457
+ }
46458
+
46023
46459
  // src/controllers/auth-v2.controller.ts
46024
46460
  function useAuthControllerV2() {
46025
46461
  const { signUp: _signUp } = useVerificationServiceV2();
46026
46462
  const { login: _login, logout: _logout } = useAuthServiceV2();
46463
+ const { resetPassword: _resetPassword } = useUserServiceV2();
46027
46464
  async function signUp(req, res, next) {
46028
46465
  try {
46029
46466
  const validation = import_joi127.default.object({
@@ -46037,8 +46474,8 @@ function useAuthControllerV2() {
46037
46474
  });
46038
46475
  if (error) {
46039
46476
  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(", ")));
46477
+ import_node_server_utils223.logger.log({ level: "error", message: messages.join(", ") });
46478
+ next(new import_node_server_utils223.BadRequestError(messages.join(", ")));
46042
46479
  return;
46043
46480
  }
46044
46481
  const { email, password, country, orgName } = value;
@@ -46054,7 +46491,7 @@ function useAuthControllerV2() {
46054
46491
  return;
46055
46492
  } catch (error) {
46056
46493
  console.log(error);
46057
- import_node_server_utils222.logger.log({ level: "error", message: error.message });
46494
+ import_node_server_utils223.logger.log({ level: "error", message: error.message });
46058
46495
  next(error);
46059
46496
  return;
46060
46497
  }
@@ -46072,8 +46509,8 @@ function useAuthControllerV2() {
46072
46509
  });
46073
46510
  if (error) {
46074
46511
  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(", ")));
46512
+ import_node_server_utils223.logger.log({ level: "error", message: messages.join(", ") });
46513
+ next(new import_node_server_utils223.BadRequestError(messages.join(", ")));
46077
46514
  return;
46078
46515
  }
46079
46516
  const session = await _login(value);
@@ -46085,7 +46522,7 @@ function useAuthControllerV2() {
46085
46522
  res.cookie("sid", session.sid, cookieOptions).cookie("user", session.user, cookieOptions).json(session);
46086
46523
  return;
46087
46524
  } catch (error) {
46088
- import_node_server_utils222.logger.log({ level: "error", message: error.message });
46525
+ import_node_server_utils223.logger.log({ level: "error", message: error.message });
46089
46526
  next(error);
46090
46527
  return;
46091
46528
  }
@@ -46093,7 +46530,7 @@ function useAuthControllerV2() {
46093
46530
  async function logout(req, res, next) {
46094
46531
  const sid = req.headers["authorization"] ?? "";
46095
46532
  if (!sid) {
46096
- next(new import_node_server_utils222.BadRequestError("Session ID is required"));
46533
+ next(new import_node_server_utils223.BadRequestError("Session ID is required"));
46097
46534
  return;
46098
46535
  }
46099
46536
  try {
@@ -46101,127 +46538,170 @@ function useAuthControllerV2() {
46101
46538
  res.json({ message: "Logged out successfully" });
46102
46539
  return;
46103
46540
  } catch (error) {
46104
- import_node_server_utils222.logger.log({ level: "error", message: error.message });
46541
+ import_node_server_utils223.logger.log({ level: "error", message: error.message });
46105
46542
  next(error);
46106
46543
  return;
46107
46544
  }
46108
46545
  }
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();
46546
+ async function resetPassword(req, res, next) {
46547
+ const validation = import_joi127.default.object({
46548
+ otp: import_joi127.default.string().hex().required(),
46549
+ newPassword: import_joi127.default.string().required().min(8),
46550
+ passwordConfirmation: import_joi127.default.string().required().min(8)
46551
+ });
46552
+ const { error, value } = validation.validate(req.body, {
46553
+ abortEarly: false
46554
+ });
46555
+ if (error) {
46556
+ const messages = error.details.map((d) => d.message);
46557
+ import_node_server_utils223.logger.log({ level: "error", message: messages.join(", ") });
46558
+ next(new import_node_server_utils223.BadRequestError(messages.join(", ")));
46559
+ return;
46560
+ }
46561
+ const { otp, newPassword, passwordConfirmation } = value;
46137
46562
  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
46563
+ const message = await _resetPassword(
46564
+ otp,
46565
+ newPassword,
46566
+ passwordConfirmation
46186
46567
  );
46187
- await session?.commitTransaction();
46188
- return userId;
46189
- } catch (error) {
46190
- await session?.abortTransaction();
46191
- throw error;
46192
- } finally {
46193
- session?.endSession();
46568
+ res.json({ message });
46569
+ return;
46570
+ } catch (error2) {
46571
+ import_node_server_utils223.logger.log({ level: "error", message: error2.message });
46572
+ next(error2);
46573
+ return;
46194
46574
  }
46195
46575
  }
46196
46576
  return {
46197
- createUserBySignUp
46577
+ signUp,
46578
+ login,
46579
+ logout,
46580
+ resetPassword
46198
46581
  };
46199
46582
  }
46200
46583
 
46201
46584
  // src/controllers/user-v2.controller.ts
46202
46585
  var import_joi128 = __toESM(require("joi"));
46586
+ var import_multer3 = require("multer");
46203
46587
  var import_node_server_utils224 = require("@7365admin1/node-server-utils");
46204
46588
  function useUserControllerV2() {
46205
- const { createUserBySignUp: _createUserBySignUp } = useUserServiceV2();
46589
+ const {
46590
+ updateBirthday: _updateBirthday,
46591
+ getUserById: _getUserById,
46592
+ getUserByEmail: _getUserByEmail,
46593
+ getUserById: _getById,
46594
+ getUsers: _getUsers,
46595
+ getUsersByOrgId: _getUsersByOrgId,
46596
+ updateUserFieldById: _updateUserFieldById
46597
+ } = useUserRepoV2();
46598
+ const { createUserBySignUp, updateUserProfile: _updateUserProfile, updatePasswordById: _updatePasswordById } = useUserServiceV2();
46599
+ function rejectValidation(error, next) {
46600
+ const message = error.details.map((d) => d.message).join(", ");
46601
+ import_node_server_utils224.logger.log({ level: "error", message });
46602
+ next(new import_node_server_utils224.BadRequestError(message));
46603
+ }
46604
+ async function getById(req, res, next) {
46605
+ const validation = import_joi128.default.string().hex().required();
46606
+ const _id = req.params.id;
46607
+ const { error, value } = validation.validate(_id);
46608
+ if (error) {
46609
+ import_node_server_utils224.logger.log({ level: "error", message: `${error.message}` });
46610
+ next(new import_node_server_utils224.BadRequestError(error.message));
46611
+ return;
46612
+ }
46613
+ try {
46614
+ const user = await _getById(value);
46615
+ res.json(user);
46616
+ return;
46617
+ } catch (error2) {
46618
+ import_node_server_utils224.logger.log({ level: "error", message: `${error2.message}` });
46619
+ next(error2);
46620
+ return;
46621
+ }
46622
+ }
46623
+ async function getByEmail(req, res, next) {
46624
+ const { error, value } = import_joi128.default.string().email().required().validate(req.params.email);
46625
+ if (error)
46626
+ return rejectValidation(error, next);
46627
+ try {
46628
+ const user = await _getUserByEmail(value);
46629
+ res.json(user);
46630
+ return;
46631
+ } catch (err) {
46632
+ import_node_server_utils224.logger.log({ level: "error", message: `${err.message}` });
46633
+ next(err);
46634
+ return;
46635
+ }
46636
+ }
46637
+ async function getUsers(req, res, next) {
46638
+ const { search = "", page = 1, limit = 10, sort = {}, type = "", status = "active" } = req.query;
46639
+ const { error, value } = import_joi128.default.object({
46640
+ search: import_joi128.default.string().optional().allow("", null),
46641
+ page: import_joi128.default.number().integer().min(1).allow("", null).default(1),
46642
+ limit: import_joi128.default.number().integer().min(1).allow("", null).default(10),
46643
+ sort: import_joi128.default.object().optional().allow("", null).default({}),
46644
+ type: import_joi128.default.string().optional().allow("", null).default(""),
46645
+ status: import_joi128.default.string().optional().allow("", null).default("active" /* ACTIVE */)
46646
+ }).validate({ search, page, limit, sort, type, status });
46647
+ if (error)
46648
+ return rejectValidation(error, next);
46649
+ try {
46650
+ const users = await _getUsers({
46651
+ search: value.search ?? "",
46652
+ page: value.page,
46653
+ limit: value.limit,
46654
+ sort: value.sort,
46655
+ type: value.type,
46656
+ status: value.status
46657
+ });
46658
+ res.json(users);
46659
+ return;
46660
+ } catch (err) {
46661
+ next(err);
46662
+ }
46663
+ }
46664
+ async function getUsersByOrgId(req, res, next) {
46665
+ const { search, page, status, organization } = req.query;
46666
+ const { error, value } = import_joi128.default.object({
46667
+ search: import_joi128.default.string().optional().allow("", null),
46668
+ page: import_joi128.default.number().integer().min(1).allow("", null).default(1),
46669
+ status: import_joi128.default.string().required(),
46670
+ organization: import_joi128.default.string().required()
46671
+ }).validate({ search, page, status, organization });
46672
+ if (error)
46673
+ return rejectValidation(error, next);
46674
+ try {
46675
+ res.json(
46676
+ await _getUsersByOrgId({
46677
+ search: value.search ?? "",
46678
+ page: value.page,
46679
+ status: value.status,
46680
+ organization: value.organization
46681
+ })
46682
+ );
46683
+ } catch (err) {
46684
+ next(err);
46685
+ }
46686
+ }
46206
46687
  async function createUserByVerification(req, res, next) {
46207
- const schema2 = import_joi128.default.object({
46208
- id: import_joi128.default.string().hex().length(24).required(),
46688
+ const allowedTypes = ["user-sign-up" /* USER_SIGN_UP */, "user-invite" /* USER_INVITE */];
46689
+ const validation = import_joi128.default.object({
46690
+ id: import_joi128.default.string().hex().required(),
46209
46691
  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
46692
+ password: import_joi128.default.string().required(),
46693
+ type: import_joi128.default.string().required().valid(...allowedTypes)
46215
46694
  });
46695
+ const id = req.params.id;
46696
+ const payload = { ...req.body };
46697
+ const { error, value } = validation.validate({ id, ...payload });
46216
46698
  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));
46699
+ import_node_server_utils224.logger.log({ level: "error", message: `${error.message}` });
46700
+ next(new import_node_server_utils224.BadRequestError(error.message));
46220
46701
  return;
46221
46702
  }
46222
- const { id, name } = value;
46223
46703
  try {
46224
- await _createUserBySignUp({ id, name });
46704
+ await createUserBySignUp({ id: value.id, name: value.name });
46225
46705
  res.status(201).json({ message: "Successfully created account." });
46226
46706
  return;
46227
46707
  } catch (error2) {
@@ -46230,8 +46710,148 @@ function useUserControllerV2() {
46230
46710
  return;
46231
46711
  }
46232
46712
  }
46713
+ async function updateUserProfile(req, res, next) {
46714
+ if (!req.file) {
46715
+ next(new import_node_server_utils224.BadRequestError("File is required!"));
46716
+ return;
46717
+ }
46718
+ const validation = import_joi128.default.object({
46719
+ previousProfile: import_joi128.default.string().hex().optional().allow("", null)
46720
+ });
46721
+ const payload = { ...req.body };
46722
+ const { error, value } = validation.validate(payload);
46723
+ if (error) {
46724
+ import_node_server_utils224.logger.log({ level: "error", message: `${error.message}` });
46725
+ next(new import_node_server_utils224.BadRequestError(error.message));
46726
+ return;
46727
+ }
46728
+ const user = req.headers.user ?? "";
46729
+ try {
46730
+ await _updateUserProfile({
46731
+ file: req.file,
46732
+ user,
46733
+ ...value
46734
+ });
46735
+ res.json({ message: "Successfully updated profile picture." });
46736
+ return;
46737
+ } catch (error2) {
46738
+ import_node_server_utils224.logger.log({ level: "error", message: `${error2.message}` });
46739
+ next(error2);
46740
+ return;
46741
+ }
46742
+ }
46743
+ async function updateBirthday(req, res, next) {
46744
+ const MONTHS = [
46745
+ "January",
46746
+ "February",
46747
+ "March",
46748
+ "April",
46749
+ "May",
46750
+ "June",
46751
+ "July",
46752
+ "August",
46753
+ "September",
46754
+ "October",
46755
+ "November",
46756
+ "December"
46757
+ ];
46758
+ const validation = import_joi128.default.object({
46759
+ _id: import_joi128.default.string().hex().required(),
46760
+ month: import_joi128.default.string().valid(...MONTHS).required(),
46761
+ day: import_joi128.default.number().integer().min(1).max(31).required(),
46762
+ year: import_joi128.default.number().integer().min(1900).max((/* @__PURE__ */ new Date()).getFullYear()).required()
46763
+ });
46764
+ const _id = req.params.id;
46765
+ const payload = { ...req.body };
46766
+ const { error } = validation.validate({ _id, ...payload });
46767
+ if (error) {
46768
+ import_node_server_utils224.logger.log({ level: "error", message: `${error.message}` });
46769
+ next(new import_node_server_utils224.BadRequestError(error.message));
46770
+ return;
46771
+ }
46772
+ try {
46773
+ const message = await _updateBirthday({ _id, ...payload });
46774
+ res.json({ message });
46775
+ return;
46776
+ } catch (error2) {
46777
+ import_node_server_utils224.logger.log({ level: "error", message: `${error2.message}` });
46778
+ next(error2);
46779
+ return;
46780
+ }
46781
+ }
46782
+ async function updateUserFieldById(req, res, next) {
46783
+ const FIELDS = ["name", "email", "contact", "nric", "dateOfBirth", "profile", "gender", "defaultOrg"];
46784
+ const validation = import_joi128.default.object({
46785
+ _id: import_joi128.default.string().hex().required(),
46786
+ field: import_joi128.default.string().valid(...FIELDS).required(),
46787
+ value: import_joi128.default.when("field", {
46788
+ switch: [
46789
+ { is: "email", then: import_joi128.default.string().email().required() },
46790
+ { is: "defaultOrg", then: import_joi128.default.string().hex().required() }
46791
+ ],
46792
+ otherwise: import_joi128.default.string().required()
46793
+ })
46794
+ });
46795
+ const _id = req.params.id;
46796
+ const payload = { ...req.body };
46797
+ const { error } = validation.validate({ _id, ...payload });
46798
+ if (error) {
46799
+ import_node_server_utils224.logger.log({ level: "error", message: `${error.message}` });
46800
+ next(new import_node_server_utils224.BadRequestError(error.message));
46801
+ return;
46802
+ }
46803
+ try {
46804
+ const message = await _updateUserFieldById({ _id, ...payload });
46805
+ res.json({ message });
46806
+ return;
46807
+ } catch (error2) {
46808
+ import_node_server_utils224.logger.log({ level: "error", message: `${error2.message}` });
46809
+ next(error2);
46810
+ return;
46811
+ }
46812
+ }
46813
+ async function updatePasswordById(req, res, next) {
46814
+ const validation = import_joi128.default.object({
46815
+ _id: import_joi128.default.string().hex().required(),
46816
+ currentPassword: import_joi128.default.string().required().min(8),
46817
+ newPassword: import_joi128.default.string().required().min(8),
46818
+ passwordConfirmation: import_joi128.default.string().required().min(8)
46819
+ });
46820
+ const _id = req.params.id;
46821
+ const payload = { ...req.body };
46822
+ const { error } = validation.validate({
46823
+ _id,
46824
+ ...payload
46825
+ });
46826
+ if (error) {
46827
+ next(new import_node_server_utils224.BadRequestError(error.message));
46828
+ return;
46829
+ }
46830
+ const currentPassword = req.body.currentPassword ?? "";
46831
+ const newPassword = req.body.newPassword ?? "";
46832
+ const passwordConfirmation = req.body.passwordConfirmation ?? "";
46833
+ try {
46834
+ await _updatePasswordById(
46835
+ _id,
46836
+ currentPassword,
46837
+ newPassword,
46838
+ passwordConfirmation
46839
+ );
46840
+ res.json({ message: "Successfully updated password." });
46841
+ } catch (error2) {
46842
+ next(error2);
46843
+ }
46844
+ }
46233
46845
  return {
46234
- createUserByVerification
46846
+ getById,
46847
+ getByEmail,
46848
+ getUsersByOrgId,
46849
+ getUsers,
46850
+ createUserByVerification,
46851
+ updateUserProfile,
46852
+ updateBirthday,
46853
+ updateUserFieldById,
46854
+ updatePasswordById
46235
46855
  };
46236
46856
  }
46237
46857
  // Annotate the CommonJS export names for ESM import in node:
@@ -46374,6 +46994,7 @@ function useUserControllerV2() {
46374
46994
  occurrence_book_namespace_collection,
46375
46995
  orgSchema,
46376
46996
  overnight_parking_requests_namespace_collection,
46997
+ parseDahuaFind,
46377
46998
  pestDashboardCollection,
46378
46999
  poolDashboardCollection,
46379
47000
  promoCodeSchema,