@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.mjs CHANGED
@@ -1419,7 +1419,7 @@ import {
1419
1419
  import { ObjectId as ObjectId6 } from "mongodb";
1420
1420
  import Joi5 from "joi";
1421
1421
  var schemaOccurrenceEntry = Joi5.object({
1422
- site: Joi5.string().hex().required(),
1422
+ site: Joi5.string().hex().length(24).required(),
1423
1423
  dailyOccurrenceBookId: Joi5.string().hex().optional().allow(null, ""),
1424
1424
  serialNumber: Joi5.string().optional().allow(null, ""),
1425
1425
  date: Joi5.date().iso().optional().allow(null, ""),
@@ -1431,14 +1431,14 @@ var schemaOccurrenceEntry = Joi5.object({
1431
1431
  createdByName: Joi5.string().optional().allow(null, "")
1432
1432
  });
1433
1433
  var schemaUpdateOccurrenceEntry = Joi5.object({
1434
- _id: Joi5.string().hex().required(),
1434
+ _id: Joi5.string().hex().length(24).required(),
1435
1435
  serialNumber: Joi5.string().optional().allow(null, ""),
1436
1436
  date: Joi5.date().iso().optional().allow(null, ""),
1437
1437
  subject: Joi5.string().hex().optional().allow(null, ""),
1438
1438
  occurrence: Joi5.string().optional().allow(null, ""),
1439
1439
  signature: Joi5.string().hex().optional().allow(null, ""),
1440
1440
  incidentReportId: Joi5.string().hex().optional().allow(null, ""),
1441
- eSignature: Joi5.string().required(),
1441
+ eSignature: Joi5.string().hex().length(24).optional().allow(null, ""),
1442
1442
  createdByName: Joi5.string().optional().allow(null, "")
1443
1443
  });
1444
1444
  function MOccurrenceEntry(value) {
@@ -1484,6 +1484,13 @@ function MOccurrenceEntry(value) {
1484
1484
  throw new Error("Invalid incident report ID.");
1485
1485
  }
1486
1486
  }
1487
+ if (value.eSignature && typeof value.eSignature === "string") {
1488
+ try {
1489
+ value.eSignature = new ObjectId6(value.eSignature);
1490
+ } catch {
1491
+ throw new Error("Invalid incident report ID.");
1492
+ }
1493
+ }
1487
1494
  return {
1488
1495
  _id: value._id ?? new ObjectId6(),
1489
1496
  site: value.site,
@@ -1840,32 +1847,16 @@ function useOccurrenceEntryRepo() {
1840
1847
  throw error;
1841
1848
  }
1842
1849
  }
1843
- async function getOccurrenceEntryByBookId(dailyOccurrenceBookId, session) {
1850
+ async function getOccurrenceEntryByBookId(dailyOccurrenceBookId) {
1844
1851
  try {
1845
1852
  dailyOccurrenceBookId = new ObjectId7(dailyOccurrenceBookId);
1846
1853
  } catch (error) {
1847
1854
  throw new BadRequestError7("Invalid occurrence entry ID format.");
1848
1855
  }
1849
- const cacheKey = makeCacheKey4(namespace_collection, {
1850
- dailyOccurrenceBookId
1851
- });
1852
- const cachedData = await getCache(cacheKey);
1853
- if (cachedData) {
1854
- logger6.info(`Cache hit for key: ${cacheKey}`);
1855
- return cachedData;
1856
- }
1856
+ const query = { dailyOccurrenceBookId };
1857
1857
  try {
1858
- const data = await collection.findOne(
1859
- { dailyOccurrenceBookId },
1860
- {
1861
- sort: { _id: -1 },
1862
- session
1863
- }
1864
- );
1865
- setCache(cacheKey, data, 15 * 60).then(() => {
1866
- logger6.info(`Cache set for key: ${cacheKey}`);
1867
- }).catch((err) => {
1868
- logger6.error(`Failed to set cache for key: ${cacheKey}`, err);
1858
+ const data = await collection.findOne(query, {
1859
+ sort: { _id: -1 }
1869
1860
  });
1870
1861
  return data;
1871
1862
  } catch (error) {
@@ -12876,12 +12867,9 @@ import Joi40 from "joi";
12876
12867
  import {
12877
12868
  BadRequestError as BadRequestError66,
12878
12869
  InternalServerError as InternalServerError23,
12879
- logger as logger47,
12880
- makeCacheKey as makeCacheKey22,
12881
12870
  paginate as paginate17,
12882
12871
  toObjectId as toObjectId6,
12883
- useAtlas as useAtlas30,
12884
- useCache as useCache23
12872
+ useAtlas as useAtlas30
12885
12873
  } from "@7365admin1/node-server-utils";
12886
12874
 
12887
12875
  // src/models/visitor-transactions.model.ts
@@ -12901,6 +12889,7 @@ var PersonTypes = /* @__PURE__ */ ((PersonTypes3) => {
12901
12889
  PersonTypes3["GUEST"] = "guest";
12902
12890
  PersonTypes3["TENANT"] = "tenant";
12903
12891
  PersonTypes3["RESIDENT"] = "resident";
12892
+ PersonTypes3["VISITOR"] = "visitor";
12904
12893
  return PersonTypes3;
12905
12894
  })(PersonTypes || {});
12906
12895
  var PersonStatus = /* @__PURE__ */ ((PersonStatus2) => {
@@ -13088,7 +13077,6 @@ var schemaVisitorTransaction = Joi36.object({
13088
13077
  contact: Joi36.string().optional().allow(null, "")
13089
13078
  })
13090
13079
  ).optional().allow(null),
13091
- visitorPass: Joi36.string().optional().allow(null, ""),
13092
13080
  unitName: Joi36.string().optional().allow(null, ""),
13093
13081
  expiredAt: Joi36.date().iso().optional().allow(null, ""),
13094
13082
  arrivalTime: Joi36.string().pattern(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().allow(null, "").messages({
@@ -13097,7 +13085,15 @@ var schemaVisitorTransaction = Joi36.object({
13097
13085
  duration: Joi36.number().integer().optional().allow(null),
13098
13086
  isOvernightParking: Joi36.boolean().optional().default(false),
13099
13087
  email: Joi36.string().email().optional().allow(null, ""),
13100
- numberOfPassengers: Joi36.number().integer().optional().allow(null, "")
13088
+ numberOfPassengers: Joi36.number().integer().optional().allow(null, ""),
13089
+ visitorPass: Joi36.array().items(
13090
+ Joi36.string().hex().length(24).optional().allow(null)
13091
+ ),
13092
+ passKeys: Joi36.array().items(
13093
+ Joi36.string().hex().length(24).optional().allow(null)
13094
+ ),
13095
+ checkInRemarks: Joi36.string().optional().allow("", null),
13096
+ checkOutRemarks: Joi36.string().optional().allow("", null)
13101
13097
  });
13102
13098
  var schemaUpdateVisTrans = Joi36.object({
13103
13099
  _id: Joi36.string().hex().length(24).required(),
@@ -13123,7 +13119,15 @@ var schemaUpdateVisTrans = Joi36.object({
13123
13119
  status: Joi36.string().optional().allow(null, ""),
13124
13120
  remarks: Joi36.string().optional().allow(null, ""),
13125
13121
  manualCheckout: Joi36.boolean().optional().allow(null),
13126
- expiredAt: Joi36.date().iso().optional().allow(null, "")
13122
+ expiredAt: Joi36.date().iso().optional().allow(null, ""),
13123
+ visitorPass: Joi36.array().items(
13124
+ Joi36.string().hex().length(24).optional().allow(null)
13125
+ ),
13126
+ passKeys: Joi36.array().items(
13127
+ Joi36.string().hex().length(24).optional().allow(null)
13128
+ ),
13129
+ checkInRemarks: Joi36.string().optional().allow("", null),
13130
+ checkOutRemarks: Joi36.string().optional().allow("", null)
13127
13131
  });
13128
13132
  function MVisitorTransaction(value) {
13129
13133
  const { error } = schemaVisitorTransaction.validate(value, {
@@ -13167,6 +13171,14 @@ function MVisitorTransaction(value) {
13167
13171
  throw new Error("Invalid type for manualCheckout key.");
13168
13172
  }
13169
13173
  }
13174
+ if (value.visitorPass && Array.isArray(value.visitorPass) && value.visitorPass.length > 0)
13175
+ value.visitorPass = value.visitorPass.map(
13176
+ (v) => typeof v === "string" ? new ObjectId39(v) : v
13177
+ );
13178
+ if (value.passKeys && Array.isArray(value.passKeys) && value.passKeys.length > 0)
13179
+ value.passKeys = value.passKeys.map(
13180
+ (p) => typeof p === "string" ? new ObjectId39(p) : p
13181
+ );
13170
13182
  const newDate = (/* @__PURE__ */ new Date()).toISOString();
13171
13183
  return {
13172
13184
  _id: value._id,
@@ -13193,7 +13205,10 @@ function MVisitorTransaction(value) {
13193
13205
  contractorType: value.contractorType,
13194
13206
  manualCheckout: value.manualCheckout ?? false,
13195
13207
  direction: value.direction,
13196
- visitorPass: value.visitorPass,
13208
+ visitorPass: value.visitorPass ?? [],
13209
+ passKeys: value.passKeys ?? [],
13210
+ checkInRemarks: value.checkInRemarks,
13211
+ checkOutRemarks: value.checkOutRemarks,
13197
13212
  unitName: value.unitName,
13198
13213
  expiredAt: value.expiredAt ?? null,
13199
13214
  createdAt: value.createdAt ?? newDate,
@@ -13211,9 +13226,6 @@ function useVisitorTransactionRepo() {
13211
13226
  throw new InternalServerError23("Unable to connect to server.");
13212
13227
  }
13213
13228
  const collection = db.collection(visitors_namespace_collection);
13214
- const { delNamespace, getCache, setCache } = useCache23(
13215
- visitors_namespace_collection
13216
- );
13217
13229
  async function createTextIndex() {
13218
13230
  try {
13219
13231
  await collection.createIndex({
@@ -13234,16 +13246,6 @@ function useVisitorTransactionRepo() {
13234
13246
  try {
13235
13247
  value = MVisitorTransaction(value);
13236
13248
  const res = await collection.insertOne(value, { session });
13237
- delNamespace().then(() => {
13238
- logger47.info(
13239
- `Cache cleared for namespace: ${visitors_namespace_collection}`
13240
- );
13241
- }).catch((err) => {
13242
- logger47.error(
13243
- `Failed to clear cache for namespace: ${visitors_namespace_collection}`,
13244
- err
13245
- );
13246
- });
13247
13249
  return res.insertedId;
13248
13250
  } catch (error) {
13249
13251
  const isDuplicated = error.message.includes("duplicate");
@@ -13266,7 +13268,7 @@ function useVisitorTransactionRepo() {
13266
13268
  type = "",
13267
13269
  checkedOut,
13268
13270
  plateNumber = ""
13269
- }, session) {
13271
+ }) {
13270
13272
  page = page > 0 ? page - 1 : 0;
13271
13273
  const skip = page * limit;
13272
13274
  let checkOutFilter;
@@ -13301,26 +13303,6 @@ function useVisitorTransactionRepo() {
13301
13303
  ...plateNumber && { plateNumber }
13302
13304
  };
13303
13305
  sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
13304
- const cacheOptions = {
13305
- status,
13306
- page,
13307
- limit,
13308
- sort: JSON.stringify(sort),
13309
- ...search && { search },
13310
- ...query.org && { org: query.org.toString() },
13311
- ...query.site && { site: query.site.toString() },
13312
- ...checkIn && { checkIn: JSON.stringify(checkIn) },
13313
- ...checkOutFilter && { checkOut: JSON.stringify(checkOutFilter) },
13314
- ...type && (Array.isArray(type) ? { type: JSON.stringify(type) } : { type }),
13315
- ...checkedOut !== void 0 && { checkedOut },
13316
- ...plateNumber && { plateNumber }
13317
- };
13318
- const cacheKey = makeCacheKey22(visitors_namespace_collection, cacheOptions);
13319
- const cachedData = await getCache(cacheKey);
13320
- if (cachedData) {
13321
- logger47.info(`Cache hit for key: ${cacheKey}`);
13322
- return cachedData;
13323
- }
13324
13306
  try {
13325
13307
  const basePipeline = [{ $match: query }];
13326
13308
  const [items, countResult] = await Promise.all([
@@ -13364,23 +13346,12 @@ function useVisitorTransactionRepo() {
13364
13346
  ]);
13365
13347
  const totalCount = countResult[0]?.total || 0;
13366
13348
  const data = paginate17(items, page, limit, totalCount);
13367
- setCache(cacheKey, data, 15 * 60).then(() => {
13368
- logger47.info(`Cache set for key: ${cacheKey}`);
13369
- }).catch((err) => {
13370
- logger47.error(`Failed to set cache for key: ${cacheKey}`, err);
13371
- });
13372
13349
  return data;
13373
13350
  } catch (error) {
13374
13351
  throw error;
13375
13352
  }
13376
13353
  }
13377
13354
  async function getVisitorTransactionById(id) {
13378
- const cacheKey = makeCacheKey22(visitors_namespace_collection, { id });
13379
- const cachedData = await getCache(cacheKey);
13380
- if (cachedData) {
13381
- logger47.info(`Cache hit for key: ${cacheKey}`);
13382
- return cachedData;
13383
- }
13384
13355
  const _id = toObjectId6(id);
13385
13356
  try {
13386
13357
  const basePipeline = [{ $match: { _id } }];
@@ -13417,38 +13388,20 @@ function useVisitorTransactionRepo() {
13417
13388
  }
13418
13389
  }
13419
13390
  ]).toArray();
13420
- setCache(cacheKey, result, 15 * 60).then(() => {
13421
- logger47.info(`Cache set for key: ${cacheKey}`);
13422
- }).catch((err) => {
13423
- logger47.error(`Failed to set cache for key: ${cacheKey}`, err);
13424
- });
13425
13391
  return result;
13426
13392
  } catch (error) {
13427
13393
  throw error;
13428
13394
  }
13429
13395
  }
13430
13396
  async function getOpenByPlateNumber(plateNumber, site) {
13431
- const _site = typeof site === "string" ? site : toObjectId6(site);
13432
- const cacheKey = makeCacheKey22(visitors_namespace_collection, {
13397
+ const _site = typeof site === "string" ? toObjectId6(site) : site;
13398
+ const query = {
13433
13399
  plateNumber,
13434
- key: "get-open-transaction-plate-number",
13435
- site
13436
- });
13400
+ site: _site,
13401
+ checkOut: null
13402
+ };
13437
13403
  try {
13438
- const cacheData = await getCache(cacheKey);
13439
- if (cacheData) {
13440
- logger47.info(`Cache hit for key: ${cacheKey}`);
13441
- return cacheData;
13442
- }
13443
- const data = await collection.findOne(
13444
- { plateNumber, site: _site, checkOut: null },
13445
- { sort: { _id: -1 } }
13446
- );
13447
- setCache(cacheKey, data, 15 * 60).then(() => {
13448
- logger47.info(`Cache set for key: ${cacheKey}`);
13449
- }).catch((err) => {
13450
- logger47.error(`Failed to set cache for key: ${cacheKey}`, err);
13451
- });
13404
+ const data = await collection.findOne(query);
13452
13405
  return data;
13453
13406
  } catch (error) {
13454
13407
  throw new InternalServerError23(
@@ -13472,16 +13425,6 @@ function useVisitorTransactionRepo() {
13472
13425
  { $set: value },
13473
13426
  { session }
13474
13427
  );
13475
- delNamespace().then(() => {
13476
- logger47.info(
13477
- `Cache cleared for namespace: ${visitors_namespace_collection}`
13478
- );
13479
- }).catch((err) => {
13480
- logger47.error(
13481
- `Failed to clear cache for namespace: ${visitors_namespace_collection}`,
13482
- err
13483
- );
13484
- });
13485
13428
  return result;
13486
13429
  } catch (error) {
13487
13430
  throw error;
@@ -13503,16 +13446,6 @@ function useVisitorTransactionRepo() {
13503
13446
  if (res.modifiedCount === 0) {
13504
13447
  throw new InternalServerError23("Unable to delete visitor transaction.");
13505
13448
  }
13506
- delNamespace().then(() => {
13507
- logger47.info(
13508
- `Cache cleared for namespace: ${visitors_namespace_collection}`
13509
- );
13510
- }).catch((err) => {
13511
- logger47.error(
13512
- `Failed to clear cache for namespace: ${visitors_namespace_collection}`,
13513
- err
13514
- );
13515
- });
13516
13449
  return res.modifiedCount;
13517
13450
  } catch (error) {
13518
13451
  throw error;
@@ -13578,16 +13511,6 @@ function useVisitorTransactionRepo() {
13578
13511
  },
13579
13512
  { session }
13580
13513
  );
13581
- delNamespace().then(() => {
13582
- logger47.info(
13583
- `Cache cleared for namespace: ${visitors_namespace_collection}`
13584
- );
13585
- }).catch((err) => {
13586
- logger47.error(
13587
- `Failed to clear cache for namespace: ${visitors_namespace_collection}`,
13588
- err
13589
- );
13590
- });
13591
13514
  return res;
13592
13515
  } catch (error) {
13593
13516
  throw error;
@@ -13619,6 +13542,7 @@ var VehicleType = /* @__PURE__ */ ((VehicleType2) => {
13619
13542
  var VehicleCategory = /* @__PURE__ */ ((VehicleCategory2) => {
13620
13543
  VehicleCategory2["RESIDENT"] = "resident";
13621
13544
  VehicleCategory2["VISITOR"] = "visitor";
13545
+ VehicleCategory2["GUEST"] = "guest";
13622
13546
  return VehicleCategory2;
13623
13547
  })(VehicleCategory || {});
13624
13548
  var VehicleStatus = /* @__PURE__ */ ((VehicleStatus2) => {
@@ -13663,7 +13587,7 @@ var vehicleSchema = Joi37.object({
13663
13587
  return value;
13664
13588
  }).required(),
13665
13589
  type: Joi37.string().required().valid(...Object.values(VehicleType)),
13666
- category: Joi37.string().required().valid(...Object.values(VehicleCategory)),
13590
+ category: Joi37.string().required().valid(...Object.values(PersonTypes)),
13667
13591
  name: Joi37.string().required(),
13668
13592
  phoneNumber: Joi37.string().optional().allow("", null),
13669
13593
  recNo: Joi37.string().optional().allow("", null),
@@ -13801,12 +13725,10 @@ import {
13801
13725
  BadRequestError as BadRequestError68,
13802
13726
  InternalServerError as InternalServerError24,
13803
13727
  logger as logger49,
13804
- makeCacheKey as makeCacheKey23,
13805
13728
  NotFoundError as NotFoundError17,
13806
13729
  paginate as paginate18,
13807
13730
  toObjectId as toObjectId7,
13808
- useAtlas as useAtlas31,
13809
- useCache as useCache24
13731
+ useAtlas as useAtlas31
13810
13732
  } from "@7365admin1/node-server-utils";
13811
13733
  import { ObjectId as ObjectId42 } from "mongodb";
13812
13734
  import Joi38 from "joi";
@@ -13818,9 +13740,6 @@ function useVehicleRepo() {
13818
13740
  throw new InternalServerError24("Unable to connect to server.");
13819
13741
  }
13820
13742
  const collection = db.collection(vehicles_namespace_collection);
13821
- const { delNamespace, setCache, getCache } = useCache24(
13822
- vehicles_namespace_collection
13823
- );
13824
13743
  async function createIndex() {
13825
13744
  try {
13826
13745
  await collection.createIndexes([
@@ -13852,16 +13771,6 @@ function useVehicleRepo() {
13852
13771
  try {
13853
13772
  value = MVehicle(value);
13854
13773
  const res = await collection.insertOne(value, { session });
13855
- delNamespace().then(() => {
13856
- logger49.info(
13857
- `Cache cleared for namespace: ${vehicles_namespace_collection}`
13858
- );
13859
- }).catch((err) => {
13860
- logger49.error(
13861
- `Failed to clear cache for namespace: ${vehicles_namespace_collection}`,
13862
- err
13863
- );
13864
- });
13865
13774
  return res.insertedId;
13866
13775
  } catch (error) {
13867
13776
  logger49.log({
@@ -13886,29 +13795,12 @@ function useVehicleRepo() {
13886
13795
  }) {
13887
13796
  page = page > 0 ? page - 1 : 0;
13888
13797
  const baseQuery = {
13889
- ...status && { status },
13890
- ...type && { type },
13891
- ...category && { category }
13892
- };
13893
- let query = { ...baseQuery };
13894
- const cacheOptions = {
13895
13798
  ...status && { status },
13896
13799
  ...type && { type },
13897
13800
  ...category && { category },
13898
- page: String(page),
13899
- limit: String(limit),
13900
- sort: JSON.stringify(sort)
13801
+ ...search && { $text: { search } }
13901
13802
  };
13902
- if (search) {
13903
- query.$text = { $search: search };
13904
- cacheOptions.search = search;
13905
- }
13906
- const cacheKey = makeCacheKey23(vehicles_namespace_collection, cacheOptions);
13907
- const cachedData = await getCache(cacheKey);
13908
- if (cachedData) {
13909
- logger49.info(`Cache hit for key: ${cacheKey}`);
13910
- return cachedData;
13911
- }
13803
+ let query = { ...baseQuery };
13912
13804
  const escapeRegex = (input) => input.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
13913
13805
  const buildGroupedPipeline = (matchQuery) => [
13914
13806
  { $match: matchQuery },
@@ -14066,9 +13958,6 @@ function useVehicleRepo() {
14066
13958
  length = regexCountResult[0]?.total || 0;
14067
13959
  }
14068
13960
  const data = paginate18(items, page, limit, length);
14069
- setCache(cacheKey, data, 15 * 60).then(() => logger49.info(`Cache set for key: ${cacheKey}`)).catch(
14070
- (err) => logger49.error(`Failed to set cache for key: ${cacheKey}`, err)
14071
- );
14072
13961
  return data;
14073
13962
  } catch (error) {
14074
13963
  throw error;
@@ -14080,14 +13969,6 @@ function useVehicleRepo() {
14080
13969
  } catch (error) {
14081
13970
  throw new BadRequestError68("Invalid site ID format.");
14082
13971
  }
14083
- const cacheKey = makeCacheKey23(vehicles_namespace_collection, {
14084
- site,
14085
- type: "season-pass-type-as-options"
14086
- });
14087
- const cachedData = await getCache(cacheKey);
14088
- if (cachedData) {
14089
- return cachedData;
14090
- }
14091
13972
  try {
14092
13973
  const categories = await collection.aggregate([
14093
13974
  { $match: { site } },
@@ -14107,17 +13988,6 @@ function useVehicleRepo() {
14107
13988
  },
14108
13989
  { $sort: { title: 1 } }
14109
13990
  ]).toArray();
14110
- setCache(cacheKey, categories).then(() => {
14111
- logger49.log({
14112
- level: "info",
14113
- message: `Cache set for get season pass type: ${cacheKey}`
14114
- });
14115
- }).catch((err) => {
14116
- logger49.log({
14117
- level: "error",
14118
- message: `Failed to set cache for season pass type: ${err.message}`
14119
- });
14120
- });
14121
13991
  return categories;
14122
13992
  } catch (error) {
14123
13993
  if (error instanceof BadRequestError68) {
@@ -14133,12 +14003,6 @@ function useVehicleRepo() {
14133
14003
  throw new BadRequestError68("Invalid vehicle ID format.");
14134
14004
  }
14135
14005
  try {
14136
- const cacheKey = makeCacheKey23(vehicles_namespace_collection, { _id });
14137
- const cachedData = await getCache(cacheKey);
14138
- if (cachedData) {
14139
- logger49.info(`Cache hit for key: ${cacheKey}`);
14140
- return cachedData;
14141
- }
14142
14006
  const data = await collection.aggregate([
14143
14007
  { $match: { _id } },
14144
14008
  { $limit: 1 },
@@ -14308,11 +14172,6 @@ function useVehicleRepo() {
14308
14172
  throw new NotFoundError17("Vehicle not found.");
14309
14173
  }
14310
14174
  const result = data[0];
14311
- setCache(cacheKey, result, 15 * 60).then(() => {
14312
- logger49.info(`Cache set for key: ${cacheKey}`);
14313
- }).catch((err) => {
14314
- logger49.error(`Failed to set cache for key: ${cacheKey}`, err);
14315
- });
14316
14175
  return result;
14317
14176
  } catch (error) {
14318
14177
  throw error;
@@ -14324,15 +14183,6 @@ function useVehicleRepo() {
14324
14183
  throw new BadRequestError68(error.details[0].message);
14325
14184
  }
14326
14185
  try {
14327
- const cacheKey = makeCacheKey23(vehicles_namespace_collection, {
14328
- plateNumber: value,
14329
- status: "active"
14330
- });
14331
- const cachedData = await getCache(cacheKey);
14332
- if (cachedData) {
14333
- logger49.info(`Cache hit for key: ${cacheKey}`);
14334
- return cachedData;
14335
- }
14336
14186
  const data = await collection.findOne({
14337
14187
  plateNumber: value,
14338
14188
  status: "active"
@@ -14340,11 +14190,6 @@ function useVehicleRepo() {
14340
14190
  if (!data) {
14341
14191
  throw new NotFoundError17("Vehicle not found.");
14342
14192
  }
14343
- setCache(cacheKey, data, 15 * 60).then(() => {
14344
- logger49.info(`Cache set for key: ${cacheKey}`);
14345
- }).catch((err) => {
14346
- logger49.error(`Failed to set cache for key: ${cacheKey}`, err);
14347
- });
14348
14193
  return data;
14349
14194
  } catch (error2) {
14350
14195
  throw error2;
@@ -14369,16 +14214,6 @@ function useVehicleRepo() {
14369
14214
  if (res.modifiedCount === 0) {
14370
14215
  throw new InternalServerError24("Unable to update vehicle.");
14371
14216
  }
14372
- delNamespace().then(() => {
14373
- logger49.info(
14374
- `Cache cleared for namespace: ${vehicles_namespace_collection}`
14375
- );
14376
- }).catch((err) => {
14377
- logger49.error(
14378
- `Failed to clear cache for namespace: ${vehicles_namespace_collection}`,
14379
- err
14380
- );
14381
- });
14382
14217
  return res.modifiedCount;
14383
14218
  } catch (error) {
14384
14219
  throw error;
@@ -14402,16 +14237,6 @@ function useVehicleRepo() {
14402
14237
  );
14403
14238
  if (res.modifiedCount === 0)
14404
14239
  throw new InternalServerError24("Unable to delete vehicle.");
14405
- delNamespace().then(() => {
14406
- logger49.info(
14407
- `Cache cleared for namespace: ${vehicles_namespace_collection}`
14408
- );
14409
- }).catch((err) => {
14410
- logger49.error(
14411
- `Failed to clear cache for namespace: ${vehicles_namespace_collection}`,
14412
- err
14413
- );
14414
- });
14415
14240
  return res.modifiedCount;
14416
14241
  } catch (error) {
14417
14242
  throw error;
@@ -14422,25 +14247,11 @@ function useVehicleRepo() {
14422
14247
  if (error) {
14423
14248
  throw new BadRequestError68(error.details[0].message);
14424
14249
  }
14425
- const cacheKey = makeCacheKey23(vehicles_namespace_collection, {
14426
- plateNumber,
14427
- status: "active"
14428
- });
14429
14250
  try {
14430
- const cacheData = await getCache(cacheKey);
14431
- if (cacheData) {
14432
- logger49.info(`Cache hit for key: ${cacheKey}`);
14433
- return cacheData;
14434
- }
14435
14251
  const data = await collection.findOne(
14436
14252
  { plateNumber, status: "active" },
14437
14253
  { sort: { _id: -1 } }
14438
14254
  );
14439
- setCache(cacheKey, data, 15 * 60).then(() => {
14440
- logger49.info(`Cache set for key: ${cacheKey}`);
14441
- }).catch((err) => {
14442
- logger49.error(`Failed to set cache for key: ${cacheKey}`, err);
14443
- });
14444
14255
  return data;
14445
14256
  } catch (error2) {
14446
14257
  throw new InternalServerError24(
@@ -14464,19 +14275,6 @@ function useVehicleRepo() {
14464
14275
  nric: _nric
14465
14276
  };
14466
14277
  sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
14467
- const cacheOptions = {
14468
- deletedAt: "",
14469
- nric: _nric,
14470
- page: String(page),
14471
- limit: String(limit),
14472
- sort: JSON.stringify(sort)
14473
- };
14474
- const cacheKey = makeCacheKey23(vehicles_namespace_collection, cacheOptions);
14475
- const cachedData = await getCache(cacheKey);
14476
- if (cachedData) {
14477
- logger49.info(`Cache hit for key: ${cacheKey}`);
14478
- return cachedData;
14479
- }
14480
14278
  try {
14481
14279
  const items = await collection.aggregate([
14482
14280
  { $match: query },
@@ -14497,9 +14295,6 @@ function useVehicleRepo() {
14497
14295
  ]).toArray();
14498
14296
  const length = await collection.countDocuments(query);
14499
14297
  const data = paginate18(items, page, limit, length);
14500
- setCache(cacheKey, data, 15 * 60).then(() => logger49.info(`Cache set for key: ${cacheKey}`)).catch(
14501
- (err) => logger49.error(`Failed to set cache for key: ${cacheKey}`, err)
14502
- );
14503
14298
  return data;
14504
14299
  } catch (error) {
14505
14300
  throw error;
@@ -14514,19 +14309,9 @@ function useVehicleRepo() {
14514
14309
  end: { $exists: true, $lte: now }
14515
14310
  // check only end
14516
14311
  },
14517
- { $set: { status: "deleted", deletedAt: now } },
14312
+ { $set: { status: "deleted", deletedAt: now, isDeletedInDahua: true } },
14518
14313
  { session }
14519
14314
  );
14520
- delNamespace().then(() => {
14521
- logger49.info(
14522
- `Cache cleared for namespace: ${vehicles_namespace_collection}`
14523
- );
14524
- }).catch((err) => {
14525
- logger49.error(
14526
- `Failed to clear cache for namespace: ${vehicles_namespace_collection}`,
14527
- err
14528
- );
14529
- });
14530
14315
  return res.modifiedCount;
14531
14316
  } catch (error) {
14532
14317
  throw error;
@@ -14545,21 +14330,6 @@ function useVehicleRepo() {
14545
14330
  const query = {
14546
14331
  unit
14547
14332
  };
14548
- const cacheOptions = {
14549
- unit: unitId,
14550
- page,
14551
- limit,
14552
- sort: JSON.stringify(sort)
14553
- };
14554
- const cacheKey = makeCacheKey23(
14555
- vehicles_namespace_collection,
14556
- cacheOptions
14557
- );
14558
- const cachedData = await getCache(cacheKey);
14559
- if (cachedData) {
14560
- logger49.info(`Cache hit for key: ${cacheKey}`);
14561
- return cachedData;
14562
- }
14563
14333
  const items = await collection.find(query, {
14564
14334
  projection: {
14565
14335
  createdAt: 0,
@@ -14572,14 +14342,24 @@ function useVehicleRepo() {
14572
14342
  }).toArray();
14573
14343
  const length = await collection.countDocuments(query);
14574
14344
  const data = paginate18(items, page, limit, length);
14575
- setCache(cacheKey, data, 15 * 60).then(() => logger49.info(`Cache set for key: ${cacheKey}`)).catch(
14576
- (err) => logger49.error(`Failed to set cache for key: ${cacheKey}`, err)
14577
- );
14578
14345
  return data;
14579
14346
  } catch (error) {
14580
14347
  throw error;
14581
14348
  }
14582
14349
  }
14350
+ async function getAllExpiredVehicles() {
14351
+ try {
14352
+ const now = (/* @__PURE__ */ new Date()).toISOString();
14353
+ const query = {
14354
+ end: { $lte: now },
14355
+ status: { $ne: "deleted" }
14356
+ };
14357
+ const items = await collection.find(query).toArray();
14358
+ return items;
14359
+ } catch (error) {
14360
+ throw error;
14361
+ }
14362
+ }
14583
14363
  return {
14584
14364
  createIndex,
14585
14365
  createTextIndex,
@@ -14593,7 +14373,8 @@ function useVehicleRepo() {
14593
14373
  getVehicleByPlateNumber,
14594
14374
  getVehiclesByNRIC,
14595
14375
  deleteExpiredVehicles,
14596
- getAllVehiclesByUnitId
14376
+ getAllVehiclesByUnitId,
14377
+ getAllExpiredVehicles
14597
14378
  };
14598
14379
  }
14599
14380
 
@@ -15220,18 +15001,32 @@ function formatDahuaDate(date) {
15220
15001
  date.getSeconds()
15221
15002
  )}`;
15222
15003
  }
15004
+ function parseDahuaFind(text) {
15005
+ const found = Number(text.match(/found=(\d+)/)?.[1] || 0);
15006
+ if (!found) {
15007
+ return { exists: false };
15008
+ }
15009
+ return {
15010
+ exists: true,
15011
+ recNo: text.match(/records\[0\]\.RecNo=(.*)/)?.[1]?.trim(),
15012
+ plateNumber: text.match(/records\[0\]\.PlateNumber=(.*)/)?.[1]?.trim()
15013
+ };
15014
+ }
15223
15015
  function useVehicleService() {
15224
15016
  const {
15225
15017
  add: _add,
15226
15018
  deleteVehicle: _deleteVehicle,
15227
15019
  updateVehicleById: _updateVehicleById,
15228
15020
  getVehicleById: _getVehicleById,
15229
- deleteExpiredVehicles: _deleteExpiredVehicles
15021
+ deleteExpiredVehicles: _deleteExpiredVehicles,
15022
+ getVehicleByPlateNumber: _getVehicleByPlateNumber,
15023
+ getAllExpiredVehicles: _getAllExpiredVehicles
15230
15024
  } = useVehicleRepo();
15231
15025
  const {
15232
15026
  addPlateNumber: _addPlateNumber,
15233
15027
  removePlateNumber: _removePlateNumber,
15234
- updatePlateNumber: _updatePlateNumber
15028
+ updatePlateNumber: _updatePlateNumber,
15029
+ getPlateNumber: _getPlateNumber
15235
15030
  } = useDahuaService();
15236
15031
  const { getAllCameraWithPassword: _getAllSiteCameras } = useSiteCameraRepo();
15237
15032
  const { getById: _getById } = useOrgRepo();
@@ -15242,9 +15037,15 @@ function useVehicleService() {
15242
15037
  if (!session) {
15243
15038
  throw new Error("Unable to start session for vehicle service.");
15244
15039
  }
15245
- const org = await _getById(value.org);
15040
+ const [_vehiclePlateNumber] = value.plateNumber;
15041
+ const [existingPlateNumber, org] = await Promise.all([
15042
+ _getVehicleByPlateNumber(_vehiclePlateNumber),
15043
+ _getById(value.org)
15044
+ ]);
15246
15045
  if (!org)
15247
15046
  throw new BadRequestError70("Org not found");
15047
+ if (existingPlateNumber)
15048
+ throw new BadRequestError70("Vehicle plate number already exists");
15248
15049
  if (!Object.values(OrgNature).includes(org.nature)) {
15249
15050
  throw new BadRequestError70(
15250
15051
  "This organization is not allowed to add vehicles."
@@ -15324,29 +15125,61 @@ function useVehicleService() {
15324
15125
  if (vehicleValue.status && vehicleValue.status !== "pending" /* PENDING */) {
15325
15126
  for (const camera of siteCameras) {
15326
15127
  const { host, username, password } = camera;
15327
- const dahuaPayload = {
15128
+ const plateNumber2 = vehicleValue.plateNumber;
15129
+ const dahuaQuery = {
15328
15130
  host,
15329
15131
  username,
15330
15132
  password,
15331
- plateNumber,
15332
- mode: _mode,
15333
- owner,
15334
- ...startDateDahua ? { start: startDateDahua } : {},
15335
- ...endDateDahua ? { end: endDateDahua } : {}
15133
+ plateNumber: plateNumber2,
15134
+ mode: _mode
15336
15135
  };
15337
- const dahuaResponse = await _addPlateNumber(dahuaPayload);
15338
- if (dahuaResponse?.statusCode !== 200) {
15339
- throw new BadRequestError70(
15340
- `Failed to add plate number to ANPR ${_type}`
15341
- );
15136
+ const raw = await _getPlateNumber(dahuaQuery);
15137
+ const parsed = parseDahuaFind(raw);
15138
+ if (!parsed.exists) {
15139
+ const dahuaPayload = {
15140
+ host,
15141
+ username,
15142
+ password,
15143
+ plateNumber: plateNumber2,
15144
+ mode: _mode,
15145
+ owner,
15146
+ ...startDateDahua ? { start: startDateDahua } : {},
15147
+ ...endDateDahua ? { end: endDateDahua } : {}
15148
+ };
15149
+ const dahuaResponse = await _addPlateNumber(dahuaPayload);
15150
+ if (dahuaResponse?.statusCode !== 200) {
15151
+ throw new BadRequestError70(
15152
+ `Failed to add plate number to ANPR ${_type}`
15153
+ );
15154
+ }
15155
+ const responseData = dahuaResponse?.data?.toString("utf-8") ?? "";
15156
+ vehicleValue.recNo = responseData.split("=")[1]?.trim();
15157
+ } else {
15158
+ const dahuaPayload = {
15159
+ host,
15160
+ username,
15161
+ password,
15162
+ plateNumber: plateNumber2,
15163
+ recno: parsed.recNo,
15164
+ mode: _mode,
15165
+ ...startDateDahua ? { start: startDateDahua } : {},
15166
+ ...endDateDahua ? { end: endDateDahua } : {},
15167
+ owner,
15168
+ isOpenGate: true
15169
+ };
15170
+ const dahuaResponse = await _updatePlateNumber(dahuaPayload);
15171
+ if (dahuaResponse?.statusCode !== 200) {
15172
+ throw new BadRequestError70(
15173
+ `Failed to update plate number to ANPR ${_type}`
15174
+ );
15175
+ }
15176
+ vehicleValue.recNo = parsed.recNo;
15342
15177
  }
15343
- const responseData = dahuaResponse?.data?.toString("utf-8") ?? "";
15344
- vehicleValue.recNo = responseData.split("=")[1]?.trim();
15345
15178
  if (value.peopleId && vehicleValue.recNo) {
15346
15179
  await _pushVehicleById(
15347
15180
  value.peopleId,
15348
15181
  {
15349
- plateNumber,
15182
+ plateNumber: plateNumber2,
15350
15183
  recNo: vehicleValue.recNo
15351
15184
  },
15352
15185
  session
@@ -15537,6 +15370,43 @@ function useVehicleService() {
15537
15370
  }
15538
15371
  try {
15539
15372
  session.startTransaction();
15373
+ const vehicles = await _getAllExpiredVehicles();
15374
+ let siteCameras = [];
15375
+ for (const vehicle of vehicles) {
15376
+ const site = vehicle.site;
15377
+ const recno = vehicle.recNo;
15378
+ let page = 1;
15379
+ let pages = 1;
15380
+ const limit = 20;
15381
+ do {
15382
+ const siteCameraReq = await _getAllSiteCameras({
15383
+ site,
15384
+ type: "anpr",
15385
+ direction: ["both", "entry"],
15386
+ page,
15387
+ limit
15388
+ });
15389
+ pages = siteCameraReq.pages || 1;
15390
+ siteCameras.push(...siteCameraReq.items);
15391
+ page++;
15392
+ } while (page < pages);
15393
+ if (!siteCameras.length) {
15394
+ throw new BadRequestError70("No site cameras found.");
15395
+ }
15396
+ for (const camera of siteCameras) {
15397
+ const host = camera.host;
15398
+ const username = camera.username;
15399
+ const password = camera.password;
15400
+ const dahuaPayload = {
15401
+ host,
15402
+ username,
15403
+ password,
15404
+ recno,
15405
+ mode: "TrafficRedList" /* TRAFFIC_REDLIST */
15406
+ };
15407
+ await _removePlateNumber(dahuaPayload);
15408
+ }
15409
+ }
15540
15410
  await _deleteExpiredVehicles();
15541
15411
  await session.commitTransaction();
15542
15412
  return `Expired Vehicle plate numbers deleted successfully.`;
@@ -15927,21 +15797,21 @@ function useDahuaService() {
15927
15797
  org,
15928
15798
  status: "unregistered" /* UNREGISTERED */
15929
15799
  };
15930
- const typesForAutoRegister = [
15931
- "guest" /* GUEST */,
15932
- "resident" /* RESIDENT */,
15933
- "tenant" /* TENANT */
15934
- ];
15800
+ const typesForAutoRegister = Object.values(PersonTypes);
15801
+ let startDate = vehicle?.start ? new Date(vehicle?.start) : /* @__PURE__ */ new Date();
15802
+ let endDate = vehicle?.end ? new Date(vehicle?.end) : new Date(startDate.getTime() + 60 * 60 * 1e3);
15935
15803
  if (vehicle && typeof vehicle.category === "string" && typesForAutoRegister.includes(vehicle.category)) {
15936
15804
  visitorTransaction.name = vehicle.name;
15937
15805
  visitorTransaction.nric = vehicle.nric;
15938
15806
  visitorTransaction.contact = vehicle.phoneNumber;
15939
15807
  visitorTransaction.block = Number(vehicle.block);
15940
15808
  visitorTransaction.level = vehicle.level;
15941
- visitorTransaction.unit = vehicle.unit;
15809
+ visitorTransaction.unit = vehicle.unit?.toString();
15942
15810
  visitorTransaction.unitName = vehicle.unitName;
15943
15811
  visitorTransaction.type = vehicle.category;
15944
15812
  visitorTransaction.status = "registered" /* REGISTERED */;
15813
+ visitorTransaction.recNo = vehicle.recNo;
15814
+ visitorTransaction.expiredAt = vehicle.end;
15945
15815
  }
15946
15816
  const dahuaPayload = {
15947
15817
  host,
@@ -15951,13 +15821,15 @@ function useDahuaService() {
15951
15821
  mode: "TrafficRedList" /* TRAFFIC_REDLIST */,
15952
15822
  owner: vehicle?.name ?? ""
15953
15823
  };
15824
+ dahuaPayload.start = formatDahuaDate(startDate);
15825
+ dahuaPayload.end = formatDahuaDate(endDate);
15954
15826
  const shouldHaveTimeLimit = visitorTransaction.type === "guest" /* GUEST */ || visitorTransaction.status === "unregistered" /* UNREGISTERED */;
15955
15827
  if (shouldHaveTimeLimit) {
15956
- const startDate = /* @__PURE__ */ new Date();
15957
- const endDate = new Date(startDate.getTime() + 15 * 60 * 1e3);
15958
- dahuaPayload.start = formatDahuaDate(startDate);
15959
- dahuaPayload.end = formatDahuaDate(endDate);
15960
- visitorTransaction.expiredAt = endDate.toISOString();
15828
+ const startDate2 = /* @__PURE__ */ new Date();
15829
+ const endDate2 = new Date(startDate2.getTime() + 60 * 60 * 1e3);
15830
+ dahuaPayload.start = formatDahuaDate(startDate2);
15831
+ dahuaPayload.end = formatDahuaDate(endDate2);
15832
+ visitorTransaction.expiredAt = endDate2.toISOString();
15961
15833
  }
15962
15834
  try {
15963
15835
  await addPlateNumber(dahuaPayload);
@@ -16206,14 +16078,14 @@ function useDahuaService() {
16206
16078
  start: Joi39.string().isoDate().optional().allow("", null),
16207
16079
  end: Joi39.string().isoDate().optional().allow("", null),
16208
16080
  owner: Joi39.string().optional().allow("", null),
16209
- openGate: Joi39.boolean().optional().allow(null)
16081
+ isOpenGate: Joi39.boolean().optional().allow(null)
16210
16082
  });
16211
16083
  const { error } = validation.validate(value);
16212
16084
  if (error) {
16213
16085
  throw new BadRequestError71(`Validation error: ${error.message}`);
16214
16086
  }
16215
16087
  value.owner = String(value.owner ?? "").substring(0, 15) || "unknown";
16216
- const _openGate = String(value.openGate);
16088
+ const _openGate = String(value.isOpenGate);
16217
16089
  const isOpenGateString = _openGate && _openGate !== "undefined" ? _openGate : "true";
16218
16090
  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}`;
16219
16091
  try {
@@ -16274,7 +16146,7 @@ function useDahuaService() {
16274
16146
  username: Joi39.string().required(),
16275
16147
  password: Joi39.string().required(),
16276
16148
  recno: Joi39.string().required(),
16277
- mode: Joi39.string().valid("TrafficBlackList", "TrafficRedList").required()
16149
+ mode: Joi39.string().valid(...Object.values(ANPRMode)).required()
16278
16150
  });
16279
16151
  const { error } = validation.validate(value);
16280
16152
  if (error) {
@@ -16292,12 +16164,39 @@ function useDahuaService() {
16292
16164
  logger52.error(`[${value.host}] Error removing plate number:`, error2);
16293
16165
  }
16294
16166
  }
16167
+ async function getPlateNumber(value) {
16168
+ const validation = Joi39.object({
16169
+ host: Joi39.string().required(),
16170
+ username: Joi39.string().required(),
16171
+ password: Joi39.string().required(),
16172
+ plateNumber: Joi39.string().required(),
16173
+ mode: Joi39.string().valid(...Object.values(ANPRMode)).required()
16174
+ });
16175
+ const { error } = validation.validate(value);
16176
+ if (error) {
16177
+ throw new BadRequestError71(`Validation error: ${error.message}`);
16178
+ }
16179
+ try {
16180
+ const response = await useDahuaDigest({
16181
+ host: value.host,
16182
+ username: value.username,
16183
+ password: value.password,
16184
+ endpoint: `/cgi-bin/recordFinder.cgi?action=find&name=${value.mode}&condition.PlateNumber=${encodeURIComponent(value.plateNumber)}`
16185
+ });
16186
+ const text = response?.data?.toString?.("utf-8");
16187
+ return text;
16188
+ } catch (error2) {
16189
+ logger52.error(`[${value.host}] Error finding plate number:`, error2);
16190
+ throw error2;
16191
+ }
16192
+ }
16295
16193
  return {
16296
16194
  getSnapshot,
16297
16195
  getTrafficJunction,
16298
16196
  addPlateNumber,
16299
16197
  removePlateNumber,
16300
- updatePlateNumber
16198
+ updatePlateNumber,
16199
+ getPlateNumber
16301
16200
  };
16302
16201
  }
16303
16202
 
@@ -20630,10 +20529,13 @@ function useVisitorTransactionService() {
20630
20529
  const { getSiteById: _getSiteById } = useSiteRepo();
20631
20530
  const {
20632
20531
  addPlateNumber: _addPlateNumber,
20633
- removePlateNumber: _removePlateNumber
20532
+ removePlateNumber: _removePlateNumber,
20533
+ getPlateNumber: _getPlateNumber,
20534
+ updatePlateNumber: _updatePlateNumber
20634
20535
  } = useDahuaService();
20635
20536
  const { getAllSites: _getAllSites } = useSiteRepo();
20636
20537
  const { getByUserId: _getByUserId } = usePersonRepo();
20538
+ const { add: addVehicle } = useVehicleRepo();
20637
20539
  async function add(value) {
20638
20540
  const session = useAtlas47.getClient()?.startSession();
20639
20541
  const allowedPersonTypes = [
@@ -20650,12 +20552,12 @@ function useVisitorTransactionService() {
20650
20552
  let site;
20651
20553
  if (value.site) {
20652
20554
  [camera, site] = await Promise.all([
20653
- _getBySite(value.site, { type: "anpr" }),
20555
+ _getBySite(value.site, { type: "anpr" /* ANPR */ }),
20654
20556
  _getSiteById(value.site)
20655
20557
  ]);
20656
20558
  }
20657
- const minutesExpiration = site?.dahuaTimeExpiration ? site?.dahuaTimeExpiration : 60;
20658
- const end = value.checkOut ? new Date(value.checkOut) : new Date(start.getTime() + minutesExpiration * 60 * 1e3);
20559
+ const hourExpiration = site?.dahuaTimeExpiration ? site?.dahuaTimeExpiration : 24 * 60;
20560
+ const end = value.checkOut ? new Date(value.checkOut) : new Date(start.getTime() + hourExpiration * 60 * 1e3);
20659
20561
  const startString = start.toISOString();
20660
20562
  const endString = end.toISOString();
20661
20563
  const startDahuaDate = formatDahuaDate(start);
@@ -20731,27 +20633,76 @@ function useVisitorTransactionService() {
20731
20633
  }
20732
20634
  }
20733
20635
  if (camera && value.plateNumber && camera.host && camera.username && camera.password) {
20734
- const dahuaPayload = {
20735
- host: camera.host,
20736
- username: camera.username,
20737
- password: camera.password,
20738
- plateNumber: value.plateNumber,
20739
- mode: "TrafficRedList" /* TRAFFIC_REDLIST */,
20740
- start: startDahuaDate,
20741
- end: endDahuaDate,
20742
- owner: value.name ?? "",
20743
- openGate: site?.isOpenGate ?? true
20636
+ const host = camera.host;
20637
+ const username = camera.username;
20638
+ const password = camera.password;
20639
+ const mode = "TrafficRedList" /* TRAFFIC_REDLIST */;
20640
+ const _plateNumber = value.plateNumber;
20641
+ const dahuaQuery = {
20642
+ host,
20643
+ username,
20644
+ password,
20645
+ plateNumber: _plateNumber,
20646
+ mode
20744
20647
  };
20745
- const dahuaResponse = await _addPlateNumber(dahuaPayload);
20746
- if (dahuaResponse?.statusCode !== 200) {
20747
- throw new BadRequestError96(
20748
- `Failed to add plate number to ANPR whitelist`
20749
- );
20648
+ const raw = await _getPlateNumber(dahuaQuery);
20649
+ const parsed = parseDahuaFind(raw);
20650
+ if (!parsed.exists) {
20651
+ const dahuaPayload = {
20652
+ host,
20653
+ username,
20654
+ password,
20655
+ plateNumber: _plateNumber,
20656
+ mode,
20657
+ start: startDahuaDate,
20658
+ end: endDahuaDate,
20659
+ owner: value.name ?? "",
20660
+ isOpenGate: site?.isOpenGate ?? true
20661
+ };
20662
+ const dahuaResponse = await _addPlateNumber(dahuaPayload);
20663
+ if (dahuaResponse?.statusCode !== 200) {
20664
+ throw new BadRequestError96(
20665
+ `Failed to add plate number to ANPR whitelist`
20666
+ );
20667
+ }
20668
+ const responseData = dahuaResponse?.data?.toString("utf-8") ?? "";
20669
+ value.recNo = responseData.split("=")[1]?.trim();
20670
+ value.checkIn = startString;
20671
+ value.expiredAt = endString;
20672
+ const vehiclePayload = {
20673
+ name: value.name ?? "",
20674
+ category: value.type,
20675
+ org: value.org,
20676
+ site: value.site,
20677
+ plateNumber: value.plateNumber,
20678
+ type: "whitelist" /* WHITELIST */,
20679
+ nric: value.nric,
20680
+ start: startString,
20681
+ end: endString,
20682
+ recNo: value.recNo
20683
+ };
20684
+ await addVehicle(vehiclePayload);
20685
+ } else {
20686
+ const dahuaPayload = {
20687
+ host,
20688
+ username,
20689
+ password,
20690
+ plateNumber: _plateNumber,
20691
+ recno: parsed.recNo,
20692
+ mode,
20693
+ start: startDahuaDate,
20694
+ end: endDahuaDate,
20695
+ owner: value.name ?? "",
20696
+ isOpenGate: site?.isOpenGate ?? true
20697
+ };
20698
+ const dahuaResponse = await _updatePlateNumber(dahuaPayload);
20699
+ if (dahuaResponse?.statusCode !== 200) {
20700
+ throw new BadRequestError96(
20701
+ `Failed to update plate number to ANPR ${"whitelist" /* WHITELIST */}`
20702
+ );
20703
+ }
20704
+ value.recNo = parsed.recNo;
20750
20705
  }
20751
- const responseData = dahuaResponse?.data?.toString("utf-8") ?? "";
20752
- value.recNo = responseData.split("=")[1]?.trim();
20753
- value.checkIn = startString;
20754
- value.expiredAt = endString;
20755
20706
  }
20756
20707
  const result = await _add(value, session);
20757
20708
  await session?.commitTransaction();
@@ -21085,7 +21036,6 @@ function useVisitorTransactionController() {
21085
21036
  }
21086
21037
  }
21087
21038
  async function inviteVisitor(req, res, next) {
21088
- const inviter = req.params.inviterId;
21089
21039
  const schema2 = Joi55.object({
21090
21040
  name: Joi55.string().required(),
21091
21041
  contact: Joi55.string().required(),
@@ -39091,8 +39041,7 @@ function useOccurrenceEntryController() {
39091
39041
  getLatestSerialNumber: _getLatestSerialNumber
39092
39042
  } = useOccurrenceEntryRepo();
39093
39043
  async function add(req, res, next) {
39094
- const payload = { ...req.body };
39095
- const { error } = schemaOccurrenceEntry.validate(payload, {
39044
+ const { error, value } = schemaOccurrenceEntry.validate(req.body, {
39096
39045
  abortEarly: false
39097
39046
  });
39098
39047
  if (error) {
@@ -39102,7 +39051,7 @@ function useOccurrenceEntryController() {
39102
39051
  return;
39103
39052
  }
39104
39053
  try {
39105
- const data = await _add(payload);
39054
+ const data = await _add(value);
39106
39055
  res.status(201).json(data);
39107
39056
  return;
39108
39057
  } catch (error2) {
@@ -39184,9 +39133,8 @@ function useOccurrenceEntryController() {
39184
39133
  }
39185
39134
  }
39186
39135
  async function updateOccurrenceEntryById(req, res, next) {
39187
- const _id = req.params.id;
39188
- const payload = { _id, ...req.body };
39189
- const { error } = schemaUpdateOccurrenceEntry.validate(payload, {
39136
+ const payload = { _id: req.params.id, ...req.body };
39137
+ const { error, value } = schemaUpdateOccurrenceEntry.validate(payload, {
39190
39138
  abortEarly: false
39191
39139
  });
39192
39140
  if (error) {
@@ -39195,8 +39143,9 @@ function useOccurrenceEntryController() {
39195
39143
  next(new BadRequestError170(messages));
39196
39144
  return;
39197
39145
  }
39146
+ const { _id, ...rest } = value;
39198
39147
  try {
39199
- const result = await _updateOccurrenceEntryById(_id, req.body);
39148
+ const result = await _updateOccurrenceEntryById(_id, rest);
39200
39149
  res.status(200).json({ message: result });
39201
39150
  return;
39202
39151
  } catch (error2) {
@@ -45503,12 +45452,6 @@ function useVerificationRepoV2() {
45503
45452
  err
45504
45453
  );
45505
45454
  });
45506
- const cacheKey = makeCacheKey64(namespace_collection, { _id });
45507
- delCache(cacheKey).then(() => {
45508
- logger175.info(`Cache deleted for key: ${cacheKey}`);
45509
- }).catch((err) => {
45510
- logger175.error(`Failed to delete cache for key: ${cacheKey}`, err);
45511
- });
45512
45455
  return result;
45513
45456
  } catch (error) {
45514
45457
  throw new InternalServerError68("Error updating verification status.");
@@ -45924,9 +45867,12 @@ function useVerificationControllerV2() {
45924
45867
  async function verify(req, res, next) {
45925
45868
  try {
45926
45869
  const schema2 = Joi126.object({ verificationCode: Joi126.string().required() });
45927
- const { error, value } = schema2.validate({
45928
- verificationCode: req.params.verificationCode
45929
- });
45870
+ const { error, value } = schema2.validate(
45871
+ {
45872
+ verificationCode: req.params.verificationCode
45873
+ },
45874
+ { abortEarly: false }
45875
+ );
45930
45876
  if (error) {
45931
45877
  const messages = error.details.map((d) => d.message).join(", ");
45932
45878
  logger177.log({ level: "error", message: messages });
@@ -45952,7 +45898,7 @@ function useVerificationControllerV2() {
45952
45898
  siteId: Joi126.string().hex().length(24).optional().allow("", null),
45953
45899
  siteName: Joi126.string().optional().allow("", null)
45954
45900
  });
45955
- const { error, value } = schema2.validate(req.body);
45901
+ const { error, value } = schema2.validate(req.body, { abortEarly: false });
45956
45902
  if (error) {
45957
45903
  const messages = error.details.map((d) => d.message).join(", ");
45958
45904
  logger177.log({ level: "error", message: messages });
@@ -45987,7 +45933,7 @@ function useVerificationControllerV2() {
45987
45933
  siteId: Joi126.string().hex().length(24).required(),
45988
45934
  siteName: Joi126.string().required()
45989
45935
  });
45990
- const { error, value } = schema2.validate(req.body);
45936
+ const { error, value } = schema2.validate(req.body, { abortEarly: false });
45991
45937
  if (error) {
45992
45938
  const messages = error.details.map((d) => d.message).join(", ");
45993
45939
  logger177.log({ level: "error", message: messages });
@@ -46013,7 +45959,7 @@ function useVerificationControllerV2() {
46013
45959
  const schema2 = Joi126.object({
46014
45960
  email: Joi126.string().email().lowercase().required()
46015
45961
  });
46016
- const { error, value } = schema2.validate(req.body);
45962
+ const { error, value } = schema2.validate(req.body, { abortEarly: false });
46017
45963
  if (error) {
46018
45964
  const messages = error.details.map((d) => d.message).join(", ");
46019
45965
  logger177.log({ level: "error", message: messages });
@@ -46043,7 +45989,7 @@ function useVerificationControllerV2() {
46043
45989
 
46044
45990
  // src/controllers/auth-v2.controller.ts
46045
45991
  import Joi127 from "joi";
46046
- import { BadRequestError as BadRequestError200, logger as logger179 } from "@7365admin1/node-server-utils";
45992
+ import { BadRequestError as BadRequestError201, logger as logger180 } from "@7365admin1/node-server-utils";
46047
45993
 
46048
45994
  // src/services/auth-v2.service.ts
46049
45995
  import {
@@ -46056,11 +46002,13 @@ import {
46056
46002
  import { v4 as uuidv42 } from "uuid";
46057
46003
 
46058
46004
  // src/repositories/user-v2.repo.ts
46005
+ import { ObjectId as ObjectId123 } from "mongodb";
46059
46006
  import {
46060
46007
  useAtlas as useAtlas113,
46061
46008
  InternalServerError as InternalServerError70,
46062
46009
  logger as logger178,
46063
46010
  BadRequestError as BadRequestError198,
46011
+ paginate as paginate58,
46064
46012
  NotFoundError as NotFoundError52,
46065
46013
  AppError as AppError27,
46066
46014
  useCache as useCache67,
@@ -46077,6 +46025,7 @@ function useUserRepoV2() {
46077
46025
  }
46078
46026
  const namespace_collection = "users";
46079
46027
  const collection = db.collection(namespace_collection);
46028
+ const { delNamespace, setCache, getCache, delCache } = useCache67(namespace_collection);
46080
46029
  async function createIndex() {
46081
46030
  try {
46082
46031
  await collection.createIndexes([{ key: { email: 1 } }]);
@@ -46086,10 +46035,7 @@ function useUserRepoV2() {
46086
46035
  }
46087
46036
  async function createTextIndex() {
46088
46037
  try {
46089
- await collection.createIndex({
46090
- name: "text",
46091
- email: "text"
46092
- });
46038
+ await collection.createIndex({ name: "text", email: "text" });
46093
46039
  } catch (error) {
46094
46040
  throw new InternalServerError70("Failed to create text index on user.");
46095
46041
  }
@@ -46104,24 +46050,22 @@ function useUserRepoV2() {
46104
46050
  throw new InternalServerError70("Failed to create unique index on user.");
46105
46051
  }
46106
46052
  }
46107
- const { delNamespace, setCache, getCache, delCache } = useCache67(namespace_collection);
46108
46053
  async function createUser(value, session) {
46109
46054
  try {
46110
46055
  value = MUser(value);
46111
46056
  const res = await collection.insertOne(value, { session });
46112
- delNamespace().then(() => {
46113
- logger178.info(`Cache cleared for namespace: ${namespace_collection}`);
46114
- }).catch((err) => {
46115
- logger178.error(
46057
+ delNamespace().then(
46058
+ () => logger178.info(`Cache cleared for namespace: ${namespace_collection}`)
46059
+ ).catch(
46060
+ (err) => logger178.error(
46116
46061
  `Failed to clear cache for namespace: ${namespace_collection}`,
46117
46062
  err
46118
- );
46119
- });
46063
+ )
46064
+ );
46120
46065
  return res.insertedId;
46121
46066
  } catch (error) {
46122
46067
  logger178.log({ level: "error", message: `${error}` });
46123
- const isDuplicated = error.message.includes("duplicate");
46124
- if (isDuplicated) {
46068
+ if (error.message.includes("duplicate")) {
46125
46069
  throw new BadRequestError198("User already exists.");
46126
46070
  }
46127
46071
  throw error;
@@ -46138,11 +46082,9 @@ function useUserRepoV2() {
46138
46082
  const data = await collection.findOne({
46139
46083
  email: { $regex: `^${email}$`, $options: "i" }
46140
46084
  });
46141
- setCache(cacheKey, data, 15 * 60).then(() => {
46142
- logger178.info(`Cache set for key: ${cacheKey}`);
46143
- }).catch((err) => {
46144
- logger178.error(`Failed to set cache for key: ${cacheKey}`, err);
46145
- });
46085
+ setCache(cacheKey, data, 15 * 60).then(() => logger178.info(`Cache set for key: ${cacheKey}`)).catch(
46086
+ (err) => logger178.error(`Failed to set cache for key: ${cacheKey}`, err)
46087
+ );
46146
46088
  return data;
46147
46089
  } catch (error) {
46148
46090
  throw new InternalServerError70("Failed to get user by email.");
@@ -46150,26 +46092,22 @@ function useUserRepoV2() {
46150
46092
  }
46151
46093
  async function getUserByEmailStatus(email) {
46152
46094
  try {
46153
- const cacheOptions = {
46095
+ const cacheKey = makeCacheKey65(namespace_collection, {
46154
46096
  email,
46155
46097
  status: "complete" /* COMPLETE */
46156
- };
46157
- const cacheKey = makeCacheKey65(namespace_collection, cacheOptions);
46098
+ });
46158
46099
  const cachedData = await getCache(cacheKey);
46159
46100
  if (cachedData) {
46160
46101
  logger178.info(`Cache hit for key: ${cacheKey}`);
46161
46102
  return cachedData;
46162
46103
  }
46163
- const query = {
46104
+ const data = await collection.findOne({
46164
46105
  email: { $regex: `^${email}$`, $options: "i" },
46165
46106
  status: "complete" /* COMPLETE */
46166
- };
46167
- const data = await collection.findOne(query);
46168
- setCache(cacheKey, data, 15 * 60).then(() => {
46169
- logger178.info(`Cache set for key: ${cacheKey}`);
46170
- }).catch((err) => {
46171
- logger178.error(`Failed to set cache for key: ${cacheKey}`, err);
46172
46107
  });
46108
+ setCache(cacheKey, data, 15 * 60).then(() => logger178.info(`Cache set for key: ${cacheKey}`)).catch(
46109
+ (err) => logger178.error(`Failed to set cache for key: ${cacheKey}`, err)
46110
+ );
46173
46111
  return data;
46174
46112
  } catch (error) {
46175
46113
  throw new InternalServerError70("Failed to get user by email.");
@@ -46192,17 +46130,10 @@ function useUserRepoV2() {
46192
46130
  let: { userOrgId: "$defaultOrg" },
46193
46131
  pipeline: [
46194
46132
  {
46195
- $match: {
46196
- $expr: { $eq: ["$orgId", "$$userOrgId"] }
46197
- }
46133
+ $match: { $expr: { $eq: ["$orgId", "$$userOrgId"] } }
46198
46134
  },
46199
46135
  {
46200
- $project: {
46201
- _id: 1,
46202
- name: 1,
46203
- type: 1,
46204
- siteId: 1
46205
- }
46136
+ $project: { _id: 1, name: 1, type: 1, siteId: 1 }
46206
46137
  }
46207
46138
  ],
46208
46139
  as: "serviceProviders"
@@ -46210,9 +46141,117 @@ function useUserRepoV2() {
46210
46141
  }
46211
46142
  ]).toArray();
46212
46143
  const data = results.length > 0 ? results[0] : null;
46213
- if (!data) {
46144
+ if (!data)
46214
46145
  throw new NotFoundError52("User not found.");
46146
+ setCache(cacheKey, data, 15 * 60).then(() => logger178.info(`Cache set for key: ${cacheKey}`)).catch(
46147
+ (err) => logger178.error(`Failed to set cache for key: ${cacheKey}`, err)
46148
+ );
46149
+ return data;
46150
+ } catch (error) {
46151
+ if (error instanceof AppError27)
46152
+ throw error;
46153
+ throw new InternalServerError70("Failed to get user by id.");
46154
+ }
46155
+ }
46156
+ async function getUserByReferralCode(referralCode) {
46157
+ try {
46158
+ const cacheKey = makeCacheKey65(namespace_collection, { referralCode });
46159
+ const cachedData = await getCache(cacheKey);
46160
+ if (cachedData) {
46161
+ logger178.info(`Cache hit for key: ${cacheKey}`);
46162
+ return cachedData;
46163
+ }
46164
+ const data = await collection.findOne({ referralCode });
46165
+ setCache(cacheKey, data, 15 * 60).then(() => logger178.info(`Cache set for key: ${cacheKey}`)).catch(
46166
+ (err) => logger178.error(`Failed to set cache for key: ${cacheKey}`, err)
46167
+ );
46168
+ return data;
46169
+ } catch (error) {
46170
+ throw new InternalServerError70("Failed to get user by referral code.");
46171
+ }
46172
+ }
46173
+ async function getByEmailApp(email, app) {
46174
+ try {
46175
+ const cacheKey = makeCacheKey65(namespace_collection, { email, app });
46176
+ const cachedData = await getCache(cacheKey);
46177
+ if (cachedData) {
46178
+ logger178.info(`Cache hit for key: ${cacheKey}`);
46179
+ return cachedData;
46215
46180
  }
46181
+ const data = await collection.findOne({
46182
+ email,
46183
+ "roles.app": app
46184
+ });
46185
+ setCache(cacheKey, data, 15 * 60).then(() => logger178.info(`Cache set for key: ${cacheKey}`)).catch(
46186
+ (err) => logger178.error(`Failed to set cache for key: ${cacheKey}`, err)
46187
+ );
46188
+ return data;
46189
+ } catch (error) {
46190
+ throw new InternalServerError70("Failed to get user by email and app.");
46191
+ }
46192
+ }
46193
+ async function getUsersByOrgId({
46194
+ organization = "",
46195
+ search = "",
46196
+ page = 1,
46197
+ limit = 10,
46198
+ sort = {},
46199
+ type = "",
46200
+ status = "active"
46201
+ }) {
46202
+ page = page > 0 ? page - 1 : 0;
46203
+ const query = { status };
46204
+ const cacheOptions = { status };
46205
+ sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
46206
+ cacheOptions.sort = JSON.stringify(sort);
46207
+ if (search) {
46208
+ query.$text = { $search: search };
46209
+ cacheOptions.search = search;
46210
+ }
46211
+ if (type) {
46212
+ query.type = type;
46213
+ cacheOptions.type = type;
46214
+ }
46215
+ if (organization) {
46216
+ try {
46217
+ query.defaultOrg = new ObjectId123(organization);
46218
+ cacheOptions.organization = organization.toString();
46219
+ } catch (error) {
46220
+ throw new BadRequestError198("Invalid organization ID format.");
46221
+ }
46222
+ }
46223
+ delNamespace().then(() => {
46224
+ logger178.info(`Cache cleared for namespace: ${namespace_collection}`);
46225
+ }).catch((err) => {
46226
+ logger178.error(
46227
+ `Failed to clear cache for namespace: ${namespace_collection}`,
46228
+ err
46229
+ );
46230
+ });
46231
+ const cacheKey = makeCacheKey65(namespace_collection, cacheOptions);
46232
+ const cachedData = await getCache(cacheKey);
46233
+ if (cachedData) {
46234
+ logger178.info(`Cache hit for key: ${cacheKey}`);
46235
+ return cachedData;
46236
+ }
46237
+ try {
46238
+ const items = await collection.aggregate([
46239
+ { $match: query },
46240
+ { $sort: sort },
46241
+ { $skip: page * limit },
46242
+ { $limit: limit },
46243
+ {
46244
+ $project: {
46245
+ _id: 1,
46246
+ name: 1,
46247
+ email: 1,
46248
+ type: 1,
46249
+ status: 1
46250
+ }
46251
+ }
46252
+ ]).toArray();
46253
+ const length = await collection.countDocuments(query);
46254
+ const data = paginate58(items, page, limit, length);
46216
46255
  setCache(cacheKey, data, 15 * 60).then(() => {
46217
46256
  logger178.info(`Cache set for key: ${cacheKey}`);
46218
46257
  }).catch((err) => {
@@ -46220,12 +46259,197 @@ function useUserRepoV2() {
46220
46259
  });
46221
46260
  return data;
46222
46261
  } catch (error) {
46223
- if (error instanceof AppError27) {
46262
+ logger178.log({ level: "error", message: `${error}` });
46263
+ throw error;
46264
+ }
46265
+ }
46266
+ async function getUsers({
46267
+ search = "",
46268
+ page = 1,
46269
+ limit = 10,
46270
+ sort = {},
46271
+ type = "",
46272
+ status = "active"
46273
+ }) {
46274
+ page = page > 0 ? page - 1 : 0;
46275
+ const query = { status };
46276
+ const cacheOptions = { status };
46277
+ sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
46278
+ cacheOptions.sort = JSON.stringify(sort);
46279
+ if (search) {
46280
+ query.$text = { $search: search };
46281
+ cacheOptions.search = search;
46282
+ }
46283
+ if (type) {
46284
+ query.type = type;
46285
+ cacheOptions.type = type;
46286
+ }
46287
+ delNamespace().then(
46288
+ () => logger178.info(`Cache cleared for namespace: ${namespace_collection}`)
46289
+ ).catch(
46290
+ (err) => logger178.error(
46291
+ `Failed to clear cache for namespace: ${namespace_collection}`,
46292
+ err
46293
+ )
46294
+ );
46295
+ const cacheKey = makeCacheKey65(namespace_collection, cacheOptions);
46296
+ const cachedData = await getCache(cacheKey);
46297
+ if (cachedData) {
46298
+ logger178.info(`Cache hit for key: ${cacheKey}`);
46299
+ return cachedData;
46300
+ }
46301
+ try {
46302
+ const items = await collection.aggregate([
46303
+ { $match: query },
46304
+ { $sort: sort },
46305
+ { $skip: page * limit },
46306
+ { $limit: limit },
46307
+ { $project: { _id: 1, name: 1, email: 1, type: 1, status: 1 } }
46308
+ ]).toArray();
46309
+ const length = await collection.countDocuments(query);
46310
+ const data = paginate58(items, page, limit, length);
46311
+ setCache(cacheKey, data, 15 * 60).then(() => logger178.info(`Cache set for key: ${cacheKey}`)).catch(
46312
+ (err) => logger178.error(`Failed to set cache for key: ${cacheKey}`, err)
46313
+ );
46314
+ return data;
46315
+ } catch (error) {
46316
+ logger178.log({ level: "error", message: `${error}` });
46317
+ throw error;
46318
+ }
46319
+ }
46320
+ async function updatePasswordById({ _id, password }, session) {
46321
+ const cacheKey = makeCacheKey65(namespace_collection, { _id });
46322
+ _id = toObjectId18(_id);
46323
+ try {
46324
+ const result = await collection.updateOne(
46325
+ { _id },
46326
+ { $set: { password, updatedAt: (/* @__PURE__ */ new Date()).toISOString() } },
46327
+ { session }
46328
+ );
46329
+ delCache(cacheKey).then(() => {
46330
+ logger178.info(`Cache deleted for key: ${cacheKey}`);
46331
+ }).catch((err) => {
46332
+ logger178.error(`Failed to delete cache for key: ${cacheKey}`, err);
46333
+ });
46334
+ return result;
46335
+ } catch (error) {
46336
+ throw new InternalServerError70("Failed to update user password.");
46337
+ }
46338
+ }
46339
+ async function updateUserFieldById({ _id, field, value } = {}, session) {
46340
+ const allowedFields = [
46341
+ "name",
46342
+ "email",
46343
+ "contact",
46344
+ "nric",
46345
+ "dateOfBirth",
46346
+ "profile",
46347
+ "gender",
46348
+ "defaultOrg"
46349
+ ];
46350
+ if (!allowedFields.includes(field)) {
46351
+ throw new BadRequestError198(
46352
+ `Field "${field}" is not allowed to be updated.`
46353
+ );
46354
+ }
46355
+ try {
46356
+ _id = new ObjectId123(_id);
46357
+ } catch (error) {
46358
+ throw new BadRequestError198("Invalid ID.");
46359
+ }
46360
+ if (field === "defaultOrg") {
46361
+ try {
46362
+ value = new ObjectId123(value);
46363
+ } catch (error) {
46364
+ throw new BadRequestError198("Invalid organization ID.");
46365
+ }
46366
+ }
46367
+ if (field === "name") {
46368
+ try {
46369
+ await Promise.all([
46370
+ updateFeedbackCreatedByName(_id, value, session),
46371
+ updateWorkOrderCreatedByName(_id, value, session),
46372
+ updateUserNameBySignatureId(_id, value, session)
46373
+ ]);
46374
+ } catch (error) {
46224
46375
  throw error;
46225
- } else {
46226
- throw new InternalServerError70("Failed to get user by email.");
46227
46376
  }
46228
46377
  }
46378
+ try {
46379
+ await collection.updateOne(
46380
+ { _id },
46381
+ { $set: { [field]: value, updatedAt: (/* @__PURE__ */ new Date()).toISOString() } },
46382
+ // Dynamically set the field
46383
+ { session }
46384
+ );
46385
+ const cacheKey = makeCacheKey65(namespace_collection, { _id });
46386
+ delCache(cacheKey).then(() => {
46387
+ logger178.info(`Cache deleted for key: ${cacheKey}`);
46388
+ }).catch((err) => {
46389
+ logger178.error(`Failed to delete cache for key: ${cacheKey}`, err);
46390
+ });
46391
+ return `Successfully updated user ${field}.`;
46392
+ } catch (error) {
46393
+ throw new InternalServerError70(`Failed to update user ${field}.`);
46394
+ }
46395
+ }
46396
+ async function updateBirthday({
46397
+ _id,
46398
+ month,
46399
+ day,
46400
+ year
46401
+ }, session) {
46402
+ try {
46403
+ _id = new ObjectId123(_id);
46404
+ } catch (error) {
46405
+ throw new BadRequestError198("Invalid user ID format.");
46406
+ }
46407
+ try {
46408
+ await collection.updateOne(
46409
+ { _id },
46410
+ {
46411
+ $set: {
46412
+ birthMonth: month,
46413
+ birthDay: day,
46414
+ birthYear: year,
46415
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
46416
+ }
46417
+ },
46418
+ { session }
46419
+ );
46420
+ const cacheKey = makeCacheKey65(namespace_collection, { _id });
46421
+ delCache(cacheKey).then(() => {
46422
+ logger178.info(`Cache deleted for key: ${cacheKey}`);
46423
+ }).catch((err) => {
46424
+ logger178.error(`Failed to delete cache for key: ${cacheKey}`, err);
46425
+ });
46426
+ return "Successfully updated user birthday.";
46427
+ } catch (error) {
46428
+ throw new InternalServerError70("Failed to update user birthday.");
46429
+ }
46430
+ }
46431
+ async function updatePassword({ _id, password }, session) {
46432
+ try {
46433
+ _id = new ObjectId123(_id);
46434
+ } catch (error) {
46435
+ throw new BadRequestError198("Invalid user ID format.");
46436
+ }
46437
+ try {
46438
+ const result = await collection.updateOne(
46439
+ { _id },
46440
+ { $set: { password, updatedAt: (/* @__PURE__ */ new Date()).toISOString() } },
46441
+ { session }
46442
+ );
46443
+ const cacheKey = makeCacheKey65(namespace_collection, { _id });
46444
+ delCache(cacheKey).then(() => {
46445
+ logger178.info(`Cache deleted for key: ${cacheKey}`);
46446
+ }).catch((err) => {
46447
+ logger178.error(`Failed to delete cache for key: ${cacheKey}`, err);
46448
+ });
46449
+ return result;
46450
+ } catch (error) {
46451
+ throw new InternalServerError70("Failed to update user password.");
46452
+ }
46229
46453
  }
46230
46454
  return {
46231
46455
  createIndex,
@@ -46234,7 +46458,13 @@ function useUserRepoV2() {
46234
46458
  createUser,
46235
46459
  getUserByEmail,
46236
46460
  getUserByEmailStatus,
46237
- getUserById
46461
+ getUserById,
46462
+ getUsers,
46463
+ getUsersByOrgId,
46464
+ updatePasswordById,
46465
+ updateUserFieldById,
46466
+ updateBirthday,
46467
+ updatePassword
46238
46468
  };
46239
46469
  }
46240
46470
 
@@ -46301,10 +46531,220 @@ function useAuthServiceV2() {
46301
46531
  };
46302
46532
  }
46303
46533
 
46534
+ // src/services/user-v2.service.ts
46535
+ import {
46536
+ BadRequestError as BadRequestError200,
46537
+ comparePassword as comparePassword4,
46538
+ hashPassword as hashPassword5,
46539
+ InternalServerError as InternalServerError72,
46540
+ NotFoundError as NotFoundError54,
46541
+ useAtlas as useAtlas114,
46542
+ useS3 as useS33
46543
+ } from "@7365admin1/node-server-utils";
46544
+ import "multer";
46545
+ function useUserServiceV2() {
46546
+ const {
46547
+ createUser: _createUser,
46548
+ getUserByEmail: _getUserByEmail,
46549
+ updatePasswordById: _updatePasswordById,
46550
+ updateUserFieldById: _updateUserFieldById,
46551
+ getUserById,
46552
+ updatePassword
46553
+ } = useUserRepoV2();
46554
+ const { getRoleByName, addRole } = useRoleRepo();
46555
+ const { add: addMember } = useMemberRepo();
46556
+ const { getById: getOrgById } = useOrgRepo();
46557
+ const { getSiteById } = useSiteRepo();
46558
+ const {
46559
+ getVerificationById: _getVerificationById,
46560
+ updateVerificationStatusById: _updateVerificationStatusById
46561
+ } = useVerificationRepoV2();
46562
+ const { verify: _verify } = useVerificationServiceV2();
46563
+ const { createFile, deleteFileById } = useFileRepo();
46564
+ async function createUserBySignUp({
46565
+ id = "",
46566
+ name = ""
46567
+ }) {
46568
+ const session = useAtlas114.getClient()?.startSession();
46569
+ session?.startTransaction();
46570
+ try {
46571
+ const signUp = await _getVerificationById(id);
46572
+ if (!signUp)
46573
+ throw new BadRequestError200("Invalid sign up link.");
46574
+ if (signUp.status === "complete" /* COMPLETE */)
46575
+ throw new BadRequestError200(
46576
+ "You have already an account created using this link."
46577
+ );
46578
+ const expired = signUp.expireAt < (/* @__PURE__ */ new Date()).toISOString();
46579
+ if (signUp.status === "expired" || expired)
46580
+ throw new BadRequestError200("Sign up link expired.");
46581
+ const email = signUp.email;
46582
+ const _user = await _getUserByEmail(email);
46583
+ if (_user)
46584
+ throw new BadRequestError200(`User already exists: ${email}.`);
46585
+ let org = null;
46586
+ if (signUp.metadata?.org) {
46587
+ org = await getOrgById(signUp.metadata.org);
46588
+ if (!org)
46589
+ signUp.metadata.org = "";
46590
+ }
46591
+ if (signUp.metadata?.siteId)
46592
+ await getSiteById(signUp.metadata?.siteId);
46593
+ const user = {
46594
+ email,
46595
+ password: signUp.metadata?.password,
46596
+ name,
46597
+ defaultOrg: org?._id?.toString() || ""
46598
+ };
46599
+ const userId = await _createUser(user, session);
46600
+ if (org?._id) {
46601
+ await addMember(
46602
+ {
46603
+ org: org?._id?.toString() || "",
46604
+ orgName: org?.name || "",
46605
+ user: userId.toString(),
46606
+ name,
46607
+ role: signUp.metadata?.role?.toString() || "",
46608
+ type: signUp.metadata?.app ?? "organization",
46609
+ siteId: signUp.metadata?.siteId?.toString() || "",
46610
+ siteName: signUp.metadata?.siteName || ""
46611
+ },
46612
+ session
46613
+ );
46614
+ }
46615
+ await _updateVerificationStatusById(
46616
+ id,
46617
+ "complete" /* COMPLETE */,
46618
+ session
46619
+ );
46620
+ await session?.commitTransaction();
46621
+ return userId;
46622
+ } catch (error) {
46623
+ await session?.abortTransaction();
46624
+ throw error;
46625
+ } finally {
46626
+ session?.endSession();
46627
+ }
46628
+ }
46629
+ async function resetPassword(id, newPassword, passwordConfirmation) {
46630
+ if (newPassword !== passwordConfirmation) {
46631
+ throw new BadRequestError200("Passwords do not match.");
46632
+ }
46633
+ let hashedPassword;
46634
+ const session = useAtlas114.getClient()?.startSession();
46635
+ session?.startTransaction();
46636
+ try {
46637
+ hashedPassword = await hashPassword5(newPassword);
46638
+ } catch (error) {
46639
+ throw new InternalServerError72(`Error hashing password: ${error}`);
46640
+ }
46641
+ try {
46642
+ const otpDoc = await _getVerificationById(id);
46643
+ if (!otpDoc) {
46644
+ throw new NotFoundError54("You are using an invalid reset link.");
46645
+ }
46646
+ if (otpDoc.status === "complete" /* COMPLETE */) {
46647
+ throw new BadRequestError200("This link has already been invalidated.");
46648
+ }
46649
+ const user = await _getUserByEmail(otpDoc.email);
46650
+ if (!user) {
46651
+ throw new NotFoundError54("User not found.");
46652
+ }
46653
+ if (!user._id) {
46654
+ throw new InternalServerError72("Invalid user ID.");
46655
+ }
46656
+ await Promise.all([
46657
+ _updateVerificationStatusById(id, "complete" /* COMPLETE */, session),
46658
+ _updatePasswordById(
46659
+ { _id: user._id.toString(), password: hashedPassword },
46660
+ session
46661
+ )
46662
+ ]);
46663
+ await session?.commitTransaction();
46664
+ return "Successfully reset password.";
46665
+ } catch (error) {
46666
+ await session?.abortTransaction();
46667
+ throw error;
46668
+ } finally {
46669
+ session?.endSession();
46670
+ }
46671
+ }
46672
+ const s3 = new useS33({
46673
+ accessKeyId: SPACES_ACCESS_KEY,
46674
+ secretAccessKey: SPACES_SECRET_KEY,
46675
+ endpoint: SPACES_ENDPOINT,
46676
+ region: SPACES_REGION,
46677
+ bucket: SPACES_BUCKET,
46678
+ forcePathStyle: false
46679
+ });
46680
+ async function updateUserProfile({
46681
+ file,
46682
+ user,
46683
+ previousProfile
46684
+ }) {
46685
+ const session = useAtlas114.getClient()?.startSession();
46686
+ session?.startTransaction();
46687
+ const _file = {
46688
+ name: file.originalname,
46689
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
46690
+ };
46691
+ try {
46692
+ const id = await createFile(_file, session);
46693
+ await s3.uploadObject({
46694
+ key: id,
46695
+ body: file.buffer,
46696
+ contentType: file.mimetype
46697
+ });
46698
+ if (previousProfile) {
46699
+ await deleteFileById(previousProfile, session);
46700
+ await s3.deleteObject(previousProfile);
46701
+ }
46702
+ await _updateUserFieldById(
46703
+ { _id: user, field: "profile", value: id },
46704
+ session
46705
+ );
46706
+ await session?.commitTransaction();
46707
+ return id;
46708
+ } catch (error) {
46709
+ await session?.abortTransaction();
46710
+ throw error;
46711
+ } finally {
46712
+ session?.endSession();
46713
+ }
46714
+ }
46715
+ async function updatePasswordById(id, currentPassword, newPassword, passwordConfirmation) {
46716
+ let hashedPassword;
46717
+ const user = await getUserById(id);
46718
+ const isPasswordValid = await comparePassword4(
46719
+ currentPassword,
46720
+ user.password
46721
+ );
46722
+ if (!isPasswordValid)
46723
+ throw new BadRequestError200("Invalid current password.");
46724
+ if (newPassword !== passwordConfirmation)
46725
+ throw new BadRequestError200("Passwords do not match.");
46726
+ try {
46727
+ hashedPassword = await hashPassword5(newPassword);
46728
+ if (!hashedPassword)
46729
+ throw new InternalServerError72("Error hashing password.");
46730
+ return await updatePassword({ _id: id, password: hashedPassword });
46731
+ } catch (error) {
46732
+ throw error;
46733
+ }
46734
+ }
46735
+ return {
46736
+ createUserBySignUp,
46737
+ resetPassword,
46738
+ updateUserProfile,
46739
+ updatePasswordById
46740
+ };
46741
+ }
46742
+
46304
46743
  // src/controllers/auth-v2.controller.ts
46305
46744
  function useAuthControllerV2() {
46306
46745
  const { signUp: _signUp } = useVerificationServiceV2();
46307
46746
  const { login: _login, logout: _logout } = useAuthServiceV2();
46747
+ const { resetPassword: _resetPassword } = useUserServiceV2();
46308
46748
  async function signUp(req, res, next) {
46309
46749
  try {
46310
46750
  const validation = Joi127.object({
@@ -46318,8 +46758,8 @@ function useAuthControllerV2() {
46318
46758
  });
46319
46759
  if (error) {
46320
46760
  const messages = error.details.map((d) => d.message);
46321
- logger179.log({ level: "error", message: messages.join(", ") });
46322
- next(new BadRequestError200(messages.join(", ")));
46761
+ logger180.log({ level: "error", message: messages.join(", ") });
46762
+ next(new BadRequestError201(messages.join(", ")));
46323
46763
  return;
46324
46764
  }
46325
46765
  const { email, password, country, orgName } = value;
@@ -46335,7 +46775,7 @@ function useAuthControllerV2() {
46335
46775
  return;
46336
46776
  } catch (error) {
46337
46777
  console.log(error);
46338
- logger179.log({ level: "error", message: error.message });
46778
+ logger180.log({ level: "error", message: error.message });
46339
46779
  next(error);
46340
46780
  return;
46341
46781
  }
@@ -46353,8 +46793,8 @@ function useAuthControllerV2() {
46353
46793
  });
46354
46794
  if (error) {
46355
46795
  const messages = error.details.map((d) => d.message);
46356
- logger179.log({ level: "error", message: messages.join(", ") });
46357
- next(new BadRequestError200(messages.join(", ")));
46796
+ logger180.log({ level: "error", message: messages.join(", ") });
46797
+ next(new BadRequestError201(messages.join(", ")));
46358
46798
  return;
46359
46799
  }
46360
46800
  const session = await _login(value);
@@ -46366,7 +46806,7 @@ function useAuthControllerV2() {
46366
46806
  res.cookie("sid", session.sid, cookieOptions).cookie("user", session.user, cookieOptions).json(session);
46367
46807
  return;
46368
46808
  } catch (error) {
46369
- logger179.log({ level: "error", message: error.message });
46809
+ logger180.log({ level: "error", message: error.message });
46370
46810
  next(error);
46371
46811
  return;
46372
46812
  }
@@ -46374,7 +46814,7 @@ function useAuthControllerV2() {
46374
46814
  async function logout(req, res, next) {
46375
46815
  const sid = req.headers["authorization"] ?? "";
46376
46816
  if (!sid) {
46377
- next(new BadRequestError200("Session ID is required"));
46817
+ next(new BadRequestError201("Session ID is required"));
46378
46818
  return;
46379
46819
  }
46380
46820
  try {
@@ -46382,130 +46822,170 @@ function useAuthControllerV2() {
46382
46822
  res.json({ message: "Logged out successfully" });
46383
46823
  return;
46384
46824
  } catch (error) {
46385
- logger179.log({ level: "error", message: error.message });
46825
+ logger180.log({ level: "error", message: error.message });
46386
46826
  next(error);
46387
46827
  return;
46388
46828
  }
46389
46829
  }
46390
- return {
46391
- signUp,
46392
- login,
46393
- logout
46394
- };
46395
- }
46396
-
46397
- // src/services/user-v2.service.ts
46398
- import {
46399
- BadRequestError as BadRequestError201,
46400
- useAtlas as useAtlas114
46401
- } from "@7365admin1/node-server-utils";
46402
- import "multer";
46403
- function useUserServiceV2() {
46404
- const { createUser: _createUser, getUserByEmail } = useUserRepoV2();
46405
- const { getRoleByName, addRole } = useRoleRepo();
46406
- const { add: addMember } = useMemberRepo();
46407
- const { getById: getOrgById } = useOrgRepo();
46408
- const { getSiteById } = useSiteRepo();
46409
- const {
46410
- getVerificationById: _getVerificationById,
46411
- updateVerificationStatusById: _updateVerificationStatusById
46412
- } = useVerificationRepoV2();
46413
- const { verify } = useVerificationService();
46414
- const { createFile, deleteFileById } = useFileRepo();
46415
- async function createUserBySignUp({
46416
- id = "",
46417
- name = ""
46418
- }) {
46419
- const session = useAtlas114.getClient()?.startSession();
46420
- session?.startTransaction();
46830
+ async function resetPassword(req, res, next) {
46831
+ const validation = Joi127.object({
46832
+ otp: Joi127.string().hex().required(),
46833
+ newPassword: Joi127.string().required().min(8),
46834
+ passwordConfirmation: Joi127.string().required().min(8)
46835
+ });
46836
+ const { error, value } = validation.validate(req.body, {
46837
+ abortEarly: false
46838
+ });
46839
+ if (error) {
46840
+ const messages = error.details.map((d) => d.message);
46841
+ logger180.log({ level: "error", message: messages.join(", ") });
46842
+ next(new BadRequestError201(messages.join(", ")));
46843
+ return;
46844
+ }
46845
+ const { otp, newPassword, passwordConfirmation } = value;
46421
46846
  try {
46422
- const signUp = await _getVerificationById(id);
46423
- if (!signUp)
46424
- throw new BadRequestError201("Invalid sign up link.");
46425
- if (signUp.status === "complete")
46426
- throw new BadRequestError201(
46427
- "You have already an account created using this link."
46428
- );
46429
- const expired = signUp.expireAt < (/* @__PURE__ */ new Date()).toISOString();
46430
- if (signUp.status === "expired" || expired)
46431
- throw new BadRequestError201("Sign up link expired.");
46432
- const email = signUp.email;
46433
- const _user = await getUserByEmail(email);
46434
- if (_user)
46435
- throw new BadRequestError201(`User already exists: ${email}.`);
46436
- let org = null;
46437
- if (signUp.metadata?.org) {
46438
- org = await getOrgById(signUp.metadata.org);
46439
- if (!org)
46440
- signUp.metadata.org = "";
46441
- }
46442
- if (signUp.metadata?.siteId)
46443
- await getSiteById(signUp.metadata?.siteId);
46444
- const user = {
46445
- email,
46446
- password: signUp.metadata?.password,
46447
- name,
46448
- defaultOrg: org?._id?.toString() || ""
46449
- };
46450
- const userId = await _createUser(user, session);
46451
- if (org?._id) {
46452
- await addMember(
46453
- {
46454
- org: org?._id?.toString() || "",
46455
- orgName: org?.name || "",
46456
- user: userId.toString(),
46457
- name,
46458
- role: signUp.metadata?.role?.toString() || "",
46459
- type: signUp.metadata?.app ?? "organization",
46460
- siteId: signUp.metadata?.siteId?.toString() || "",
46461
- siteName: signUp.metadata?.siteName || ""
46462
- },
46463
- session
46464
- );
46465
- }
46466
- await _updateVerificationStatusById(
46467
- id,
46468
- "complete" /* COMPLETE */,
46469
- session
46847
+ const message = await _resetPassword(
46848
+ otp,
46849
+ newPassword,
46850
+ passwordConfirmation
46470
46851
  );
46471
- await session?.commitTransaction();
46472
- return userId;
46473
- } catch (error) {
46474
- await session?.abortTransaction();
46475
- throw error;
46476
- } finally {
46477
- session?.endSession();
46852
+ res.json({ message });
46853
+ return;
46854
+ } catch (error2) {
46855
+ logger180.log({ level: "error", message: error2.message });
46856
+ next(error2);
46857
+ return;
46478
46858
  }
46479
46859
  }
46480
46860
  return {
46481
- createUserBySignUp
46861
+ signUp,
46862
+ login,
46863
+ logout,
46864
+ resetPassword
46482
46865
  };
46483
46866
  }
46484
46867
 
46485
46868
  // src/controllers/user-v2.controller.ts
46486
46869
  import Joi128 from "joi";
46870
+ import "multer";
46487
46871
  import { BadRequestError as BadRequestError202, logger as logger181 } from "@7365admin1/node-server-utils";
46488
46872
  function useUserControllerV2() {
46489
- const { createUserBySignUp: _createUserBySignUp } = useUserServiceV2();
46873
+ const {
46874
+ updateBirthday: _updateBirthday,
46875
+ getUserById: _getUserById,
46876
+ getUserByEmail: _getUserByEmail,
46877
+ getUserById: _getById,
46878
+ getUsers: _getUsers,
46879
+ getUsersByOrgId: _getUsersByOrgId,
46880
+ updateUserFieldById: _updateUserFieldById
46881
+ } = useUserRepoV2();
46882
+ const { createUserBySignUp, updateUserProfile: _updateUserProfile, updatePasswordById: _updatePasswordById } = useUserServiceV2();
46883
+ function rejectValidation(error, next) {
46884
+ const message = error.details.map((d) => d.message).join(", ");
46885
+ logger181.log({ level: "error", message });
46886
+ next(new BadRequestError202(message));
46887
+ }
46888
+ async function getById(req, res, next) {
46889
+ const validation = Joi128.string().hex().required();
46890
+ const _id = req.params.id;
46891
+ const { error, value } = validation.validate(_id);
46892
+ if (error) {
46893
+ logger181.log({ level: "error", message: `${error.message}` });
46894
+ next(new BadRequestError202(error.message));
46895
+ return;
46896
+ }
46897
+ try {
46898
+ const user = await _getById(value);
46899
+ res.json(user);
46900
+ return;
46901
+ } catch (error2) {
46902
+ logger181.log({ level: "error", message: `${error2.message}` });
46903
+ next(error2);
46904
+ return;
46905
+ }
46906
+ }
46907
+ async function getByEmail(req, res, next) {
46908
+ const { error, value } = Joi128.string().email().required().validate(req.params.email);
46909
+ if (error)
46910
+ return rejectValidation(error, next);
46911
+ try {
46912
+ const user = await _getUserByEmail(value);
46913
+ res.json(user);
46914
+ return;
46915
+ } catch (err) {
46916
+ logger181.log({ level: "error", message: `${err.message}` });
46917
+ next(err);
46918
+ return;
46919
+ }
46920
+ }
46921
+ async function getUsers(req, res, next) {
46922
+ const { search = "", page = 1, limit = 10, sort = {}, type = "", status = "active" } = req.query;
46923
+ const { error, value } = Joi128.object({
46924
+ search: Joi128.string().optional().allow("", null),
46925
+ page: Joi128.number().integer().min(1).allow("", null).default(1),
46926
+ limit: Joi128.number().integer().min(1).allow("", null).default(10),
46927
+ sort: Joi128.object().optional().allow("", null).default({}),
46928
+ type: Joi128.string().optional().allow("", null).default(""),
46929
+ status: Joi128.string().optional().allow("", null).default("active" /* ACTIVE */)
46930
+ }).validate({ search, page, limit, sort, type, status });
46931
+ if (error)
46932
+ return rejectValidation(error, next);
46933
+ try {
46934
+ const users = await _getUsers({
46935
+ search: value.search ?? "",
46936
+ page: value.page,
46937
+ limit: value.limit,
46938
+ sort: value.sort,
46939
+ type: value.type,
46940
+ status: value.status
46941
+ });
46942
+ res.json(users);
46943
+ return;
46944
+ } catch (err) {
46945
+ next(err);
46946
+ }
46947
+ }
46948
+ async function getUsersByOrgId(req, res, next) {
46949
+ const { search, page, status, organization } = req.query;
46950
+ const { error, value } = Joi128.object({
46951
+ search: Joi128.string().optional().allow("", null),
46952
+ page: Joi128.number().integer().min(1).allow("", null).default(1),
46953
+ status: Joi128.string().required(),
46954
+ organization: Joi128.string().required()
46955
+ }).validate({ search, page, status, organization });
46956
+ if (error)
46957
+ return rejectValidation(error, next);
46958
+ try {
46959
+ res.json(
46960
+ await _getUsersByOrgId({
46961
+ search: value.search ?? "",
46962
+ page: value.page,
46963
+ status: value.status,
46964
+ organization: value.organization
46965
+ })
46966
+ );
46967
+ } catch (err) {
46968
+ next(err);
46969
+ }
46970
+ }
46490
46971
  async function createUserByVerification(req, res, next) {
46491
- const schema2 = Joi128.object({
46492
- id: Joi128.string().hex().length(24).required(),
46972
+ const allowedTypes = ["user-sign-up" /* USER_SIGN_UP */, "user-invite" /* USER_INVITE */];
46973
+ const validation = Joi128.object({
46974
+ id: Joi128.string().hex().required(),
46493
46975
  name: Joi128.string().required(),
46494
- type: Joi128.string().required().valid("user-sign-up" /* USER_SIGN_UP */, "user-invite" /* USER_INVITE */)
46495
- });
46496
- const { error, value } = schema2.validate({
46497
- id: req.params.id,
46498
- ...req.body
46976
+ password: Joi128.string().required(),
46977
+ type: Joi128.string().required().valid(...allowedTypes)
46499
46978
  });
46979
+ const id = req.params.id;
46980
+ const payload = { ...req.body };
46981
+ const { error, value } = validation.validate({ id, ...payload });
46500
46982
  if (error) {
46501
- const messages = error.details.map((d) => d.message).join(", ");
46502
- logger181.log({ level: "error", message: messages });
46503
- next(new BadRequestError202(messages));
46983
+ logger181.log({ level: "error", message: `${error.message}` });
46984
+ next(new BadRequestError202(error.message));
46504
46985
  return;
46505
46986
  }
46506
- const { id, name } = value;
46507
46987
  try {
46508
- await _createUserBySignUp({ id, name });
46988
+ await createUserBySignUp({ id: value.id, name: value.name });
46509
46989
  res.status(201).json({ message: "Successfully created account." });
46510
46990
  return;
46511
46991
  } catch (error2) {
@@ -46514,8 +46994,148 @@ function useUserControllerV2() {
46514
46994
  return;
46515
46995
  }
46516
46996
  }
46997
+ async function updateUserProfile(req, res, next) {
46998
+ if (!req.file) {
46999
+ next(new BadRequestError202("File is required!"));
47000
+ return;
47001
+ }
47002
+ const validation = Joi128.object({
47003
+ previousProfile: Joi128.string().hex().optional().allow("", null)
47004
+ });
47005
+ const payload = { ...req.body };
47006
+ const { error, value } = validation.validate(payload);
47007
+ if (error) {
47008
+ logger181.log({ level: "error", message: `${error.message}` });
47009
+ next(new BadRequestError202(error.message));
47010
+ return;
47011
+ }
47012
+ const user = req.headers.user ?? "";
47013
+ try {
47014
+ await _updateUserProfile({
47015
+ file: req.file,
47016
+ user,
47017
+ ...value
47018
+ });
47019
+ res.json({ message: "Successfully updated profile picture." });
47020
+ return;
47021
+ } catch (error2) {
47022
+ logger181.log({ level: "error", message: `${error2.message}` });
47023
+ next(error2);
47024
+ return;
47025
+ }
47026
+ }
47027
+ async function updateBirthday(req, res, next) {
47028
+ const MONTHS = [
47029
+ "January",
47030
+ "February",
47031
+ "March",
47032
+ "April",
47033
+ "May",
47034
+ "June",
47035
+ "July",
47036
+ "August",
47037
+ "September",
47038
+ "October",
47039
+ "November",
47040
+ "December"
47041
+ ];
47042
+ const validation = Joi128.object({
47043
+ _id: Joi128.string().hex().required(),
47044
+ month: Joi128.string().valid(...MONTHS).required(),
47045
+ day: Joi128.number().integer().min(1).max(31).required(),
47046
+ year: Joi128.number().integer().min(1900).max((/* @__PURE__ */ new Date()).getFullYear()).required()
47047
+ });
47048
+ const _id = req.params.id;
47049
+ const payload = { ...req.body };
47050
+ const { error } = validation.validate({ _id, ...payload });
47051
+ if (error) {
47052
+ logger181.log({ level: "error", message: `${error.message}` });
47053
+ next(new BadRequestError202(error.message));
47054
+ return;
47055
+ }
47056
+ try {
47057
+ const message = await _updateBirthday({ _id, ...payload });
47058
+ res.json({ message });
47059
+ return;
47060
+ } catch (error2) {
47061
+ logger181.log({ level: "error", message: `${error2.message}` });
47062
+ next(error2);
47063
+ return;
47064
+ }
47065
+ }
47066
+ async function updateUserFieldById(req, res, next) {
47067
+ const FIELDS = ["name", "email", "contact", "nric", "dateOfBirth", "profile", "gender", "defaultOrg"];
47068
+ const validation = Joi128.object({
47069
+ _id: Joi128.string().hex().required(),
47070
+ field: Joi128.string().valid(...FIELDS).required(),
47071
+ value: Joi128.when("field", {
47072
+ switch: [
47073
+ { is: "email", then: Joi128.string().email().required() },
47074
+ { is: "defaultOrg", then: Joi128.string().hex().required() }
47075
+ ],
47076
+ otherwise: Joi128.string().required()
47077
+ })
47078
+ });
47079
+ const _id = req.params.id;
47080
+ const payload = { ...req.body };
47081
+ const { error } = validation.validate({ _id, ...payload });
47082
+ if (error) {
47083
+ logger181.log({ level: "error", message: `${error.message}` });
47084
+ next(new BadRequestError202(error.message));
47085
+ return;
47086
+ }
47087
+ try {
47088
+ const message = await _updateUserFieldById({ _id, ...payload });
47089
+ res.json({ message });
47090
+ return;
47091
+ } catch (error2) {
47092
+ logger181.log({ level: "error", message: `${error2.message}` });
47093
+ next(error2);
47094
+ return;
47095
+ }
47096
+ }
47097
+ async function updatePasswordById(req, res, next) {
47098
+ const validation = Joi128.object({
47099
+ _id: Joi128.string().hex().required(),
47100
+ currentPassword: Joi128.string().required().min(8),
47101
+ newPassword: Joi128.string().required().min(8),
47102
+ passwordConfirmation: Joi128.string().required().min(8)
47103
+ });
47104
+ const _id = req.params.id;
47105
+ const payload = { ...req.body };
47106
+ const { error } = validation.validate({
47107
+ _id,
47108
+ ...payload
47109
+ });
47110
+ if (error) {
47111
+ next(new BadRequestError202(error.message));
47112
+ return;
47113
+ }
47114
+ const currentPassword = req.body.currentPassword ?? "";
47115
+ const newPassword = req.body.newPassword ?? "";
47116
+ const passwordConfirmation = req.body.passwordConfirmation ?? "";
47117
+ try {
47118
+ await _updatePasswordById(
47119
+ _id,
47120
+ currentPassword,
47121
+ newPassword,
47122
+ passwordConfirmation
47123
+ );
47124
+ res.json({ message: "Successfully updated password." });
47125
+ } catch (error2) {
47126
+ next(error2);
47127
+ }
47128
+ }
46517
47129
  return {
46518
- createUserByVerification
47130
+ getById,
47131
+ getByEmail,
47132
+ getUsersByOrgId,
47133
+ getUsers,
47134
+ createUserByVerification,
47135
+ updateUserProfile,
47136
+ updateBirthday,
47137
+ updateUserFieldById,
47138
+ updatePasswordById
46519
47139
  };
46520
47140
  }
46521
47141
  export {
@@ -46657,6 +47277,7 @@ export {
46657
47277
  occurrence_book_namespace_collection,
46658
47278
  orgSchema,
46659
47279
  overnight_parking_requests_namespace_collection,
47280
+ parseDahuaFind,
46660
47281
  pestDashboardCollection,
46661
47282
  poolDashboardCollection,
46662
47283
  promoCodeSchema,