@7365admin1/core 2.28.1 → 2.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.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).required(),
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,
@@ -12876,12 +12883,9 @@ import Joi40 from "joi";
12876
12883
  import {
12877
12884
  BadRequestError as BadRequestError66,
12878
12885
  InternalServerError as InternalServerError23,
12879
- logger as logger47,
12880
- makeCacheKey as makeCacheKey22,
12881
12886
  paginate as paginate17,
12882
12887
  toObjectId as toObjectId6,
12883
- useAtlas as useAtlas30,
12884
- useCache as useCache23
12888
+ useAtlas as useAtlas30
12885
12889
  } from "@7365admin1/node-server-utils";
12886
12890
 
12887
12891
  // src/models/visitor-transactions.model.ts
@@ -12901,6 +12905,7 @@ var PersonTypes = /* @__PURE__ */ ((PersonTypes3) => {
12901
12905
  PersonTypes3["GUEST"] = "guest";
12902
12906
  PersonTypes3["TENANT"] = "tenant";
12903
12907
  PersonTypes3["RESIDENT"] = "resident";
12908
+ PersonTypes3["VISITOR"] = "visitor";
12904
12909
  return PersonTypes3;
12905
12910
  })(PersonTypes || {});
12906
12911
  var PersonStatus = /* @__PURE__ */ ((PersonStatus2) => {
@@ -13078,7 +13083,7 @@ var schemaVisitorTransaction = Joi36.object({
13078
13083
  checkIn: Joi36.date().optional().allow(null, ""),
13079
13084
  checkOut: Joi36.date().optional().allow(null, ""),
13080
13085
  deliveryType: Joi36.string().optional().allow(null, ""),
13081
- status: Joi36.string().optional().valid(...Object.values(VisitorStatus)).default("registered" /* REGISTERED */),
13086
+ status: Joi36.string().optional().valid(...Object.values(VisitorStatus)).default("pending" /* PENDING */),
13082
13087
  remarks: Joi36.string().optional().allow(null, ""),
13083
13088
  members: Joi36.array().items(
13084
13089
  Joi36.object({
@@ -13088,7 +13093,6 @@ var schemaVisitorTransaction = Joi36.object({
13088
13093
  contact: Joi36.string().optional().allow(null, "")
13089
13094
  })
13090
13095
  ).optional().allow(null),
13091
- visitorPass: Joi36.string().optional().allow(null, ""),
13092
13096
  unitName: Joi36.string().optional().allow(null, ""),
13093
13097
  expiredAt: Joi36.date().iso().optional().allow(null, ""),
13094
13098
  arrivalTime: Joi36.string().pattern(/^([01]\d|2[0-3]):([0-5]\d)$/).optional().allow(null, "").messages({
@@ -13097,7 +13101,15 @@ var schemaVisitorTransaction = Joi36.object({
13097
13101
  duration: Joi36.number().integer().optional().allow(null),
13098
13102
  isOvernightParking: Joi36.boolean().optional().default(false),
13099
13103
  email: Joi36.string().email().optional().allow(null, ""),
13100
- numberOfPassengers: Joi36.number().integer().optional().allow(null, "")
13104
+ numberOfPassengers: Joi36.number().integer().optional().allow(null, ""),
13105
+ visitorPass: Joi36.array().items(
13106
+ Joi36.string().hex().length(24).optional().allow(null)
13107
+ ),
13108
+ passKeys: Joi36.array().items(
13109
+ Joi36.string().hex().length(24).optional().allow(null)
13110
+ ),
13111
+ checkInRemarks: Joi36.string().optional().allow("", null),
13112
+ checkOutRemarks: Joi36.string().optional().allow("", null)
13101
13113
  });
13102
13114
  var schemaUpdateVisTrans = Joi36.object({
13103
13115
  _id: Joi36.string().hex().length(24).required(),
@@ -13123,7 +13135,15 @@ var schemaUpdateVisTrans = Joi36.object({
13123
13135
  status: Joi36.string().optional().allow(null, ""),
13124
13136
  remarks: Joi36.string().optional().allow(null, ""),
13125
13137
  manualCheckout: Joi36.boolean().optional().allow(null),
13126
- expiredAt: Joi36.date().iso().optional().allow(null, "")
13138
+ expiredAt: Joi36.date().iso().optional().allow(null, ""),
13139
+ visitorPass: Joi36.array().items(
13140
+ Joi36.string().hex().length(24).optional().allow(null)
13141
+ ),
13142
+ passKeys: Joi36.array().items(
13143
+ Joi36.string().hex().length(24).optional().allow(null)
13144
+ ),
13145
+ checkInRemarks: Joi36.string().optional().allow("", null),
13146
+ checkOutRemarks: Joi36.string().optional().allow("", null)
13127
13147
  });
13128
13148
  function MVisitorTransaction(value) {
13129
13149
  const { error } = schemaVisitorTransaction.validate(value, {
@@ -13167,6 +13187,14 @@ function MVisitorTransaction(value) {
13167
13187
  throw new Error("Invalid type for manualCheckout key.");
13168
13188
  }
13169
13189
  }
13190
+ if (value.visitorPass && Array.isArray(value.visitorPass) && value.visitorPass.length > 0)
13191
+ value.visitorPass = value.visitorPass.map(
13192
+ (v) => typeof v === "string" ? new ObjectId39(v) : v
13193
+ );
13194
+ if (value.passKeys && Array.isArray(value.passKeys) && value.passKeys.length > 0)
13195
+ value.passKeys = value.passKeys.map(
13196
+ (p) => typeof p === "string" ? new ObjectId39(p) : p
13197
+ );
13170
13198
  const newDate = (/* @__PURE__ */ new Date()).toISOString();
13171
13199
  return {
13172
13200
  _id: value._id,
@@ -13193,7 +13221,10 @@ function MVisitorTransaction(value) {
13193
13221
  contractorType: value.contractorType,
13194
13222
  manualCheckout: value.manualCheckout ?? false,
13195
13223
  direction: value.direction,
13196
- visitorPass: value.visitorPass,
13224
+ visitorPass: value.visitorPass ?? [],
13225
+ passKeys: value.passKeys ?? [],
13226
+ checkInRemarks: value.checkInRemarks,
13227
+ checkOutRemarks: value.checkOutRemarks,
13197
13228
  unitName: value.unitName,
13198
13229
  expiredAt: value.expiredAt ?? null,
13199
13230
  createdAt: value.createdAt ?? newDate,
@@ -13211,9 +13242,6 @@ function useVisitorTransactionRepo() {
13211
13242
  throw new InternalServerError23("Unable to connect to server.");
13212
13243
  }
13213
13244
  const collection = db.collection(visitors_namespace_collection);
13214
- const { delNamespace, getCache, setCache } = useCache23(
13215
- visitors_namespace_collection
13216
- );
13217
13245
  async function createTextIndex() {
13218
13246
  try {
13219
13247
  await collection.createIndex({
@@ -13234,16 +13262,6 @@ function useVisitorTransactionRepo() {
13234
13262
  try {
13235
13263
  value = MVisitorTransaction(value);
13236
13264
  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
13265
  return res.insertedId;
13248
13266
  } catch (error) {
13249
13267
  const isDuplicated = error.message.includes("duplicate");
@@ -13266,7 +13284,7 @@ function useVisitorTransactionRepo() {
13266
13284
  type = "",
13267
13285
  checkedOut,
13268
13286
  plateNumber = ""
13269
- }, session) {
13287
+ }) {
13270
13288
  page = page > 0 ? page - 1 : 0;
13271
13289
  const skip = page * limit;
13272
13290
  let checkOutFilter;
@@ -13301,26 +13319,6 @@ function useVisitorTransactionRepo() {
13301
13319
  ...plateNumber && { plateNumber }
13302
13320
  };
13303
13321
  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
13322
  try {
13325
13323
  const basePipeline = [{ $match: query }];
13326
13324
  const [items, countResult] = await Promise.all([
@@ -13364,23 +13362,12 @@ function useVisitorTransactionRepo() {
13364
13362
  ]);
13365
13363
  const totalCount = countResult[0]?.total || 0;
13366
13364
  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
13365
  return data;
13373
13366
  } catch (error) {
13374
13367
  throw error;
13375
13368
  }
13376
13369
  }
13377
13370
  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
13371
  const _id = toObjectId6(id);
13385
13372
  try {
13386
13373
  const basePipeline = [{ $match: { _id } }];
@@ -13417,38 +13404,20 @@ function useVisitorTransactionRepo() {
13417
13404
  }
13418
13405
  }
13419
13406
  ]).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
13407
  return result;
13426
13408
  } catch (error) {
13427
13409
  throw error;
13428
13410
  }
13429
13411
  }
13430
13412
  async function getOpenByPlateNumber(plateNumber, site) {
13431
- const _site = typeof site === "string" ? site : toObjectId6(site);
13432
- const cacheKey = makeCacheKey22(visitors_namespace_collection, {
13413
+ const _site = typeof site === "string" ? toObjectId6(site) : site;
13414
+ const query = {
13433
13415
  plateNumber,
13434
- key: "get-open-transaction-plate-number",
13435
- site
13436
- });
13416
+ site: _site,
13417
+ checkOut: null
13418
+ };
13437
13419
  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
- });
13420
+ const data = await collection.findOne(query);
13452
13421
  return data;
13453
13422
  } catch (error) {
13454
13423
  throw new InternalServerError23(
@@ -13472,16 +13441,6 @@ function useVisitorTransactionRepo() {
13472
13441
  { $set: value },
13473
13442
  { session }
13474
13443
  );
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
13444
  return result;
13486
13445
  } catch (error) {
13487
13446
  throw error;
@@ -13503,16 +13462,6 @@ function useVisitorTransactionRepo() {
13503
13462
  if (res.modifiedCount === 0) {
13504
13463
  throw new InternalServerError23("Unable to delete visitor transaction.");
13505
13464
  }
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
13465
  return res.modifiedCount;
13517
13466
  } catch (error) {
13518
13467
  throw error;
@@ -13578,16 +13527,6 @@ function useVisitorTransactionRepo() {
13578
13527
  },
13579
13528
  { session }
13580
13529
  );
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
13530
  return res;
13592
13531
  } catch (error) {
13593
13532
  throw error;
@@ -13619,6 +13558,7 @@ var VehicleType = /* @__PURE__ */ ((VehicleType2) => {
13619
13558
  var VehicleCategory = /* @__PURE__ */ ((VehicleCategory2) => {
13620
13559
  VehicleCategory2["RESIDENT"] = "resident";
13621
13560
  VehicleCategory2["VISITOR"] = "visitor";
13561
+ VehicleCategory2["GUEST"] = "guest";
13622
13562
  return VehicleCategory2;
13623
13563
  })(VehicleCategory || {});
13624
13564
  var VehicleStatus = /* @__PURE__ */ ((VehicleStatus2) => {
@@ -13663,7 +13603,7 @@ var vehicleSchema = Joi37.object({
13663
13603
  return value;
13664
13604
  }).required(),
13665
13605
  type: Joi37.string().required().valid(...Object.values(VehicleType)),
13666
- category: Joi37.string().required().valid(...Object.values(VehicleCategory)),
13606
+ category: Joi37.string().required().valid(...Object.values(PersonTypes)),
13667
13607
  name: Joi37.string().required(),
13668
13608
  phoneNumber: Joi37.string().optional().allow("", null),
13669
13609
  recNo: Joi37.string().optional().allow("", null),
@@ -13801,12 +13741,10 @@ import {
13801
13741
  BadRequestError as BadRequestError68,
13802
13742
  InternalServerError as InternalServerError24,
13803
13743
  logger as logger49,
13804
- makeCacheKey as makeCacheKey23,
13805
13744
  NotFoundError as NotFoundError17,
13806
13745
  paginate as paginate18,
13807
13746
  toObjectId as toObjectId7,
13808
- useAtlas as useAtlas31,
13809
- useCache as useCache24
13747
+ useAtlas as useAtlas31
13810
13748
  } from "@7365admin1/node-server-utils";
13811
13749
  import { ObjectId as ObjectId42 } from "mongodb";
13812
13750
  import Joi38 from "joi";
@@ -13818,9 +13756,6 @@ function useVehicleRepo() {
13818
13756
  throw new InternalServerError24("Unable to connect to server.");
13819
13757
  }
13820
13758
  const collection = db.collection(vehicles_namespace_collection);
13821
- const { delNamespace, setCache, getCache } = useCache24(
13822
- vehicles_namespace_collection
13823
- );
13824
13759
  async function createIndex() {
13825
13760
  try {
13826
13761
  await collection.createIndexes([
@@ -13852,16 +13787,6 @@ function useVehicleRepo() {
13852
13787
  try {
13853
13788
  value = MVehicle(value);
13854
13789
  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
13790
  return res.insertedId;
13866
13791
  } catch (error) {
13867
13792
  logger49.log({
@@ -13886,29 +13811,12 @@ function useVehicleRepo() {
13886
13811
  }) {
13887
13812
  page = page > 0 ? page - 1 : 0;
13888
13813
  const baseQuery = {
13889
- ...status && { status },
13890
- ...type && { type },
13891
- ...category && { category }
13892
- };
13893
- let query = { ...baseQuery };
13894
- const cacheOptions = {
13895
13814
  ...status && { status },
13896
13815
  ...type && { type },
13897
13816
  ...category && { category },
13898
- page: String(page),
13899
- limit: String(limit),
13900
- sort: JSON.stringify(sort)
13817
+ ...search && { $text: { search } }
13901
13818
  };
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
- }
13819
+ let query = { ...baseQuery };
13912
13820
  const escapeRegex = (input) => input.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
13913
13821
  const buildGroupedPipeline = (matchQuery) => [
13914
13822
  { $match: matchQuery },
@@ -14066,9 +13974,6 @@ function useVehicleRepo() {
14066
13974
  length = regexCountResult[0]?.total || 0;
14067
13975
  }
14068
13976
  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
13977
  return data;
14073
13978
  } catch (error) {
14074
13979
  throw error;
@@ -14080,14 +13985,6 @@ function useVehicleRepo() {
14080
13985
  } catch (error) {
14081
13986
  throw new BadRequestError68("Invalid site ID format.");
14082
13987
  }
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
13988
  try {
14092
13989
  const categories = await collection.aggregate([
14093
13990
  { $match: { site } },
@@ -14107,17 +14004,6 @@ function useVehicleRepo() {
14107
14004
  },
14108
14005
  { $sort: { title: 1 } }
14109
14006
  ]).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
14007
  return categories;
14122
14008
  } catch (error) {
14123
14009
  if (error instanceof BadRequestError68) {
@@ -14133,12 +14019,6 @@ function useVehicleRepo() {
14133
14019
  throw new BadRequestError68("Invalid vehicle ID format.");
14134
14020
  }
14135
14021
  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
14022
  const data = await collection.aggregate([
14143
14023
  { $match: { _id } },
14144
14024
  { $limit: 1 },
@@ -14308,11 +14188,6 @@ function useVehicleRepo() {
14308
14188
  throw new NotFoundError17("Vehicle not found.");
14309
14189
  }
14310
14190
  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
14191
  return result;
14317
14192
  } catch (error) {
14318
14193
  throw error;
@@ -14324,15 +14199,6 @@ function useVehicleRepo() {
14324
14199
  throw new BadRequestError68(error.details[0].message);
14325
14200
  }
14326
14201
  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
14202
  const data = await collection.findOne({
14337
14203
  plateNumber: value,
14338
14204
  status: "active"
@@ -14340,11 +14206,6 @@ function useVehicleRepo() {
14340
14206
  if (!data) {
14341
14207
  throw new NotFoundError17("Vehicle not found.");
14342
14208
  }
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
14209
  return data;
14349
14210
  } catch (error2) {
14350
14211
  throw error2;
@@ -14369,16 +14230,6 @@ function useVehicleRepo() {
14369
14230
  if (res.modifiedCount === 0) {
14370
14231
  throw new InternalServerError24("Unable to update vehicle.");
14371
14232
  }
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
14233
  return res.modifiedCount;
14383
14234
  } catch (error) {
14384
14235
  throw error;
@@ -14402,16 +14253,6 @@ function useVehicleRepo() {
14402
14253
  );
14403
14254
  if (res.modifiedCount === 0)
14404
14255
  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
14256
  return res.modifiedCount;
14416
14257
  } catch (error) {
14417
14258
  throw error;
@@ -14422,25 +14263,11 @@ function useVehicleRepo() {
14422
14263
  if (error) {
14423
14264
  throw new BadRequestError68(error.details[0].message);
14424
14265
  }
14425
- const cacheKey = makeCacheKey23(vehicles_namespace_collection, {
14426
- plateNumber,
14427
- status: "active"
14428
- });
14429
14266
  try {
14430
- const cacheData = await getCache(cacheKey);
14431
- if (cacheData) {
14432
- logger49.info(`Cache hit for key: ${cacheKey}`);
14433
- return cacheData;
14434
- }
14435
14267
  const data = await collection.findOne(
14436
14268
  { plateNumber, status: "active" },
14437
14269
  { sort: { _id: -1 } }
14438
14270
  );
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
14271
  return data;
14445
14272
  } catch (error2) {
14446
14273
  throw new InternalServerError24(
@@ -14464,19 +14291,6 @@ function useVehicleRepo() {
14464
14291
  nric: _nric
14465
14292
  };
14466
14293
  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
14294
  try {
14481
14295
  const items = await collection.aggregate([
14482
14296
  { $match: query },
@@ -14497,9 +14311,6 @@ function useVehicleRepo() {
14497
14311
  ]).toArray();
14498
14312
  const length = await collection.countDocuments(query);
14499
14313
  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
14314
  return data;
14504
14315
  } catch (error) {
14505
14316
  throw error;
@@ -14514,19 +14325,9 @@ function useVehicleRepo() {
14514
14325
  end: { $exists: true, $lte: now }
14515
14326
  // check only end
14516
14327
  },
14517
- { $set: { status: "deleted", deletedAt: now } },
14328
+ { $set: { status: "deleted", deletedAt: now, isDeletedInDahua: true } },
14518
14329
  { session }
14519
14330
  );
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
14331
  return res.modifiedCount;
14531
14332
  } catch (error) {
14532
14333
  throw error;
@@ -14545,21 +14346,6 @@ function useVehicleRepo() {
14545
14346
  const query = {
14546
14347
  unit
14547
14348
  };
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
14349
  const items = await collection.find(query, {
14564
14350
  projection: {
14565
14351
  createdAt: 0,
@@ -14572,14 +14358,24 @@ function useVehicleRepo() {
14572
14358
  }).toArray();
14573
14359
  const length = await collection.countDocuments(query);
14574
14360
  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
14361
  return data;
14579
14362
  } catch (error) {
14580
14363
  throw error;
14581
14364
  }
14582
14365
  }
14366
+ async function getAllExpiredVehicles() {
14367
+ try {
14368
+ const now = (/* @__PURE__ */ new Date()).toISOString();
14369
+ const query = {
14370
+ end: { $lte: now },
14371
+ status: { $ne: "deleted" }
14372
+ };
14373
+ const items = await collection.find(query).toArray();
14374
+ return items;
14375
+ } catch (error) {
14376
+ throw error;
14377
+ }
14378
+ }
14583
14379
  return {
14584
14380
  createIndex,
14585
14381
  createTextIndex,
@@ -14593,7 +14389,8 @@ function useVehicleRepo() {
14593
14389
  getVehicleByPlateNumber,
14594
14390
  getVehiclesByNRIC,
14595
14391
  deleteExpiredVehicles,
14596
- getAllVehiclesByUnitId
14392
+ getAllVehiclesByUnitId,
14393
+ getAllExpiredVehicles
14597
14394
  };
14598
14395
  }
14599
14396
 
@@ -15220,18 +15017,32 @@ function formatDahuaDate(date) {
15220
15017
  date.getSeconds()
15221
15018
  )}`;
15222
15019
  }
15020
+ function parseDahuaFind(text) {
15021
+ const found = Number(text.match(/found=(\d+)/)?.[1] || 0);
15022
+ if (!found) {
15023
+ return { exists: false };
15024
+ }
15025
+ return {
15026
+ exists: true,
15027
+ recNo: text.match(/records\[0\]\.RecNo=(.*)/)?.[1]?.trim(),
15028
+ plateNumber: text.match(/records\[0\]\.PlateNumber=(.*)/)?.[1]?.trim()
15029
+ };
15030
+ }
15223
15031
  function useVehicleService() {
15224
15032
  const {
15225
15033
  add: _add,
15226
15034
  deleteVehicle: _deleteVehicle,
15227
15035
  updateVehicleById: _updateVehicleById,
15228
15036
  getVehicleById: _getVehicleById,
15229
- deleteExpiredVehicles: _deleteExpiredVehicles
15037
+ deleteExpiredVehicles: _deleteExpiredVehicles,
15038
+ getVehicleByPlateNumber: _getVehicleByPlateNumber,
15039
+ getAllExpiredVehicles: _getAllExpiredVehicles
15230
15040
  } = useVehicleRepo();
15231
15041
  const {
15232
15042
  addPlateNumber: _addPlateNumber,
15233
15043
  removePlateNumber: _removePlateNumber,
15234
- updatePlateNumber: _updatePlateNumber
15044
+ updatePlateNumber: _updatePlateNumber,
15045
+ getPlateNumber: _getPlateNumber
15235
15046
  } = useDahuaService();
15236
15047
  const { getAllCameraWithPassword: _getAllSiteCameras } = useSiteCameraRepo();
15237
15048
  const { getById: _getById } = useOrgRepo();
@@ -15242,9 +15053,15 @@ function useVehicleService() {
15242
15053
  if (!session) {
15243
15054
  throw new Error("Unable to start session for vehicle service.");
15244
15055
  }
15245
- const org = await _getById(value.org);
15056
+ const [_vehiclePlateNumber] = value.plateNumber;
15057
+ const [existingPlateNumber, org] = await Promise.all([
15058
+ _getVehicleByPlateNumber(_vehiclePlateNumber),
15059
+ _getById(value.org)
15060
+ ]);
15246
15061
  if (!org)
15247
15062
  throw new BadRequestError70("Org not found");
15063
+ if (existingPlateNumber)
15064
+ throw new BadRequestError70("Vehicle plate number already exists");
15248
15065
  if (!Object.values(OrgNature).includes(org.nature)) {
15249
15066
  throw new BadRequestError70(
15250
15067
  "This organization is not allowed to add vehicles."
@@ -15324,29 +15141,61 @@ function useVehicleService() {
15324
15141
  if (vehicleValue.status && vehicleValue.status !== "pending" /* PENDING */) {
15325
15142
  for (const camera of siteCameras) {
15326
15143
  const { host, username, password } = camera;
15327
- const dahuaPayload = {
15144
+ const plateNumber2 = vehicleValue.plateNumber;
15145
+ const dahuaQuery = {
15328
15146
  host,
15329
15147
  username,
15330
15148
  password,
15331
- plateNumber,
15332
- mode: _mode,
15333
- owner,
15334
- ...startDateDahua ? { start: startDateDahua } : {},
15335
- ...endDateDahua ? { end: endDateDahua } : {}
15149
+ plateNumber: plateNumber2,
15150
+ mode: _mode
15336
15151
  };
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
- );
15152
+ const raw = await _getPlateNumber(dahuaQuery);
15153
+ const parsed = parseDahuaFind(raw);
15154
+ if (!parsed.exists) {
15155
+ const dahuaPayload = {
15156
+ host,
15157
+ username,
15158
+ password,
15159
+ plateNumber: plateNumber2,
15160
+ mode: _mode,
15161
+ owner,
15162
+ ...startDateDahua ? { start: startDateDahua } : {},
15163
+ ...endDateDahua ? { end: endDateDahua } : {}
15164
+ };
15165
+ const dahuaResponse = await _addPlateNumber(dahuaPayload);
15166
+ if (dahuaResponse?.statusCode !== 200) {
15167
+ throw new BadRequestError70(
15168
+ `Failed to add plate number to ANPR ${_type}`
15169
+ );
15170
+ }
15171
+ const responseData = dahuaResponse?.data?.toString("utf-8") ?? "";
15172
+ vehicleValue.recNo = responseData.split("=")[1]?.trim();
15173
+ } else {
15174
+ const dahuaPayload = {
15175
+ host,
15176
+ username,
15177
+ password,
15178
+ plateNumber: plateNumber2,
15179
+ recno: parsed.recNo,
15180
+ mode: _mode,
15181
+ ...startDateDahua ? { start: startDateDahua } : {},
15182
+ ...endDateDahua ? { end: endDateDahua } : {},
15183
+ owner,
15184
+ isOpenGate: true
15185
+ };
15186
+ const dahuaResponse = await _updatePlateNumber(dahuaPayload);
15187
+ if (dahuaResponse?.statusCode !== 200) {
15188
+ throw new BadRequestError70(
15189
+ `Failed to update plate number to ANPR ${_type}`
15190
+ );
15191
+ }
15192
+ vehicleValue.recNo = parsed.recNo;
15342
15193
  }
15343
- const responseData = dahuaResponse?.data?.toString("utf-8") ?? "";
15344
- vehicleValue.recNo = responseData.split("=")[1]?.trim();
15345
15194
  if (value.peopleId && vehicleValue.recNo) {
15346
15195
  await _pushVehicleById(
15347
15196
  value.peopleId,
15348
15197
  {
15349
- plateNumber,
15198
+ plateNumber: plateNumber2,
15350
15199
  recNo: vehicleValue.recNo
15351
15200
  },
15352
15201
  session
@@ -15537,6 +15386,43 @@ function useVehicleService() {
15537
15386
  }
15538
15387
  try {
15539
15388
  session.startTransaction();
15389
+ const vehicles = await _getAllExpiredVehicles();
15390
+ let siteCameras = [];
15391
+ for (const vehicle of vehicles) {
15392
+ const site = vehicle.site;
15393
+ const recno = vehicle.recNo;
15394
+ let page = 1;
15395
+ let pages = 1;
15396
+ const limit = 20;
15397
+ do {
15398
+ const siteCameraReq = await _getAllSiteCameras({
15399
+ site,
15400
+ type: "anpr",
15401
+ direction: ["both", "entry"],
15402
+ page,
15403
+ limit
15404
+ });
15405
+ pages = siteCameraReq.pages || 1;
15406
+ siteCameras.push(...siteCameraReq.items);
15407
+ page++;
15408
+ } while (page < pages);
15409
+ if (!siteCameras.length) {
15410
+ throw new BadRequestError70("No site cameras found.");
15411
+ }
15412
+ for (const camera of siteCameras) {
15413
+ const host = camera.host;
15414
+ const username = camera.username;
15415
+ const password = camera.password;
15416
+ const dahuaPayload = {
15417
+ host,
15418
+ username,
15419
+ password,
15420
+ recno,
15421
+ mode: "TrafficRedList" /* TRAFFIC_REDLIST */
15422
+ };
15423
+ await _removePlateNumber(dahuaPayload);
15424
+ }
15425
+ }
15540
15426
  await _deleteExpiredVehicles();
15541
15427
  await session.commitTransaction();
15542
15428
  return `Expired Vehicle plate numbers deleted successfully.`;
@@ -15932,16 +15818,20 @@ function useDahuaService() {
15932
15818
  "resident" /* RESIDENT */,
15933
15819
  "tenant" /* TENANT */
15934
15820
  ];
15821
+ let startDate = vehicle?.start ? new Date(vehicle?.start) : /* @__PURE__ */ new Date();
15822
+ let endDate = vehicle?.end ? new Date(vehicle?.end) : new Date(startDate.getTime() + 60 * 60 * 1e3);
15935
15823
  if (vehicle && typeof vehicle.category === "string" && typesForAutoRegister.includes(vehicle.category)) {
15936
15824
  visitorTransaction.name = vehicle.name;
15937
15825
  visitorTransaction.nric = vehicle.nric;
15938
15826
  visitorTransaction.contact = vehicle.phoneNumber;
15939
15827
  visitorTransaction.block = Number(vehicle.block);
15940
15828
  visitorTransaction.level = vehicle.level;
15941
- visitorTransaction.unit = vehicle.unit;
15829
+ visitorTransaction.unit = vehicle.unit?.toString();
15942
15830
  visitorTransaction.unitName = vehicle.unitName;
15943
- visitorTransaction.type = vehicle.category;
15831
+ visitorTransaction.type = "resident" /* RESIDENT */;
15944
15832
  visitorTransaction.status = "registered" /* REGISTERED */;
15833
+ visitorTransaction.recNo = vehicle.recNo;
15834
+ visitorTransaction.expiredAt = vehicle.end;
15945
15835
  }
15946
15836
  const dahuaPayload = {
15947
15837
  host,
@@ -15951,13 +15841,15 @@ function useDahuaService() {
15951
15841
  mode: "TrafficRedList" /* TRAFFIC_REDLIST */,
15952
15842
  owner: vehicle?.name ?? ""
15953
15843
  };
15844
+ dahuaPayload.start = formatDahuaDate(startDate);
15845
+ dahuaPayload.end = formatDahuaDate(endDate);
15954
15846
  const shouldHaveTimeLimit = visitorTransaction.type === "guest" /* GUEST */ || visitorTransaction.status === "unregistered" /* UNREGISTERED */;
15955
15847
  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();
15848
+ const startDate2 = /* @__PURE__ */ new Date();
15849
+ const endDate2 = new Date(startDate2.getTime() + 60 * 60 * 1e3);
15850
+ dahuaPayload.start = formatDahuaDate(startDate2);
15851
+ dahuaPayload.end = formatDahuaDate(endDate2);
15852
+ visitorTransaction.expiredAt = endDate2.toISOString();
15961
15853
  }
15962
15854
  try {
15963
15855
  await addPlateNumber(dahuaPayload);
@@ -16206,14 +16098,14 @@ function useDahuaService() {
16206
16098
  start: Joi39.string().isoDate().optional().allow("", null),
16207
16099
  end: Joi39.string().isoDate().optional().allow("", null),
16208
16100
  owner: Joi39.string().optional().allow("", null),
16209
- openGate: Joi39.boolean().optional().allow(null)
16101
+ isOpenGate: Joi39.boolean().optional().allow(null)
16210
16102
  });
16211
16103
  const { error } = validation.validate(value);
16212
16104
  if (error) {
16213
16105
  throw new BadRequestError71(`Validation error: ${error.message}`);
16214
16106
  }
16215
16107
  value.owner = String(value.owner ?? "").substring(0, 15) || "unknown";
16216
- const _openGate = String(value.openGate);
16108
+ const _openGate = String(value.isOpenGate);
16217
16109
  const isOpenGateString = _openGate && _openGate !== "undefined" ? _openGate : "true";
16218
16110
  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
16111
  try {
@@ -16274,7 +16166,7 @@ function useDahuaService() {
16274
16166
  username: Joi39.string().required(),
16275
16167
  password: Joi39.string().required(),
16276
16168
  recno: Joi39.string().required(),
16277
- mode: Joi39.string().valid("TrafficBlackList", "TrafficRedList").required()
16169
+ mode: Joi39.string().valid(...Object.values(ANPRMode)).required()
16278
16170
  });
16279
16171
  const { error } = validation.validate(value);
16280
16172
  if (error) {
@@ -16292,12 +16184,39 @@ function useDahuaService() {
16292
16184
  logger52.error(`[${value.host}] Error removing plate number:`, error2);
16293
16185
  }
16294
16186
  }
16187
+ async function getPlateNumber(value) {
16188
+ const validation = Joi39.object({
16189
+ host: Joi39.string().required(),
16190
+ username: Joi39.string().required(),
16191
+ password: Joi39.string().required(),
16192
+ plateNumber: Joi39.string().required(),
16193
+ mode: Joi39.string().valid(...Object.values(ANPRMode)).required()
16194
+ });
16195
+ const { error } = validation.validate(value);
16196
+ if (error) {
16197
+ throw new BadRequestError71(`Validation error: ${error.message}`);
16198
+ }
16199
+ try {
16200
+ const response = await useDahuaDigest({
16201
+ host: value.host,
16202
+ username: value.username,
16203
+ password: value.password,
16204
+ endpoint: `/cgi-bin/recordFinder.cgi?action=find&name=${value.mode}&condition.PlateNumber=${encodeURIComponent(value.plateNumber)}`
16205
+ });
16206
+ const text = response?.data?.toString?.("utf-8");
16207
+ return text;
16208
+ } catch (error2) {
16209
+ logger52.error(`[${value.host}] Error finding plate number:`, error2);
16210
+ throw error2;
16211
+ }
16212
+ }
16295
16213
  return {
16296
16214
  getSnapshot,
16297
16215
  getTrafficJunction,
16298
16216
  addPlateNumber,
16299
16217
  removePlateNumber,
16300
- updatePlateNumber
16218
+ updatePlateNumber,
16219
+ getPlateNumber
16301
16220
  };
16302
16221
  }
16303
16222
 
@@ -20630,10 +20549,13 @@ function useVisitorTransactionService() {
20630
20549
  const { getSiteById: _getSiteById } = useSiteRepo();
20631
20550
  const {
20632
20551
  addPlateNumber: _addPlateNumber,
20633
- removePlateNumber: _removePlateNumber
20552
+ removePlateNumber: _removePlateNumber,
20553
+ getPlateNumber: _getPlateNumber,
20554
+ updatePlateNumber: _updatePlateNumber
20634
20555
  } = useDahuaService();
20635
20556
  const { getAllSites: _getAllSites } = useSiteRepo();
20636
20557
  const { getByUserId: _getByUserId } = usePersonRepo();
20558
+ const { add: addVehicle } = useVehicleRepo();
20637
20559
  async function add(value) {
20638
20560
  const session = useAtlas47.getClient()?.startSession();
20639
20561
  const allowedPersonTypes = [
@@ -20650,12 +20572,12 @@ function useVisitorTransactionService() {
20650
20572
  let site;
20651
20573
  if (value.site) {
20652
20574
  [camera, site] = await Promise.all([
20653
- _getBySite(value.site, { type: "anpr" }),
20575
+ _getBySite(value.site, { type: "anpr" /* ANPR */ }),
20654
20576
  _getSiteById(value.site)
20655
20577
  ]);
20656
20578
  }
20657
- const minutesExpiration = site?.dahuaTimeExpiration ? site?.dahuaTimeExpiration : 60;
20658
- const end = value.checkOut ? new Date(value.checkOut) : new Date(start.getTime() + minutesExpiration * 60 * 1e3);
20579
+ const hourExpiration = site?.dahuaTimeExpiration ? site?.dahuaTimeExpiration : 24 * 60;
20580
+ const end = value.checkOut ? new Date(value.checkOut) : new Date(start.getTime() + hourExpiration * 60 * 1e3);
20659
20581
  const startString = start.toISOString();
20660
20582
  const endString = end.toISOString();
20661
20583
  const startDahuaDate = formatDahuaDate(start);
@@ -20731,27 +20653,76 @@ function useVisitorTransactionService() {
20731
20653
  }
20732
20654
  }
20733
20655
  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
20656
+ const host = camera.host;
20657
+ const username = camera.username;
20658
+ const password = camera.password;
20659
+ const mode = "TrafficRedList" /* TRAFFIC_REDLIST */;
20660
+ const _plateNumber = value.plateNumber;
20661
+ const dahuaQuery = {
20662
+ host,
20663
+ username,
20664
+ password,
20665
+ plateNumber: _plateNumber,
20666
+ mode
20744
20667
  };
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
- );
20668
+ const raw = await _getPlateNumber(dahuaQuery);
20669
+ const parsed = parseDahuaFind(raw);
20670
+ if (!parsed.exists) {
20671
+ const dahuaPayload = {
20672
+ host,
20673
+ username,
20674
+ password,
20675
+ plateNumber: _plateNumber,
20676
+ mode,
20677
+ start: startDahuaDate,
20678
+ end: endDahuaDate,
20679
+ owner: value.name ?? "",
20680
+ isOpenGate: site?.isOpenGate ?? true
20681
+ };
20682
+ const dahuaResponse = await _addPlateNumber(dahuaPayload);
20683
+ if (dahuaResponse?.statusCode !== 200) {
20684
+ throw new BadRequestError96(
20685
+ `Failed to add plate number to ANPR whitelist`
20686
+ );
20687
+ }
20688
+ const responseData = dahuaResponse?.data?.toString("utf-8") ?? "";
20689
+ value.recNo = responseData.split("=")[1]?.trim();
20690
+ value.checkIn = startString;
20691
+ value.expiredAt = endString;
20692
+ const vehiclePayload = {
20693
+ name: value.name ?? "",
20694
+ category: value.type,
20695
+ org: value.org,
20696
+ site: value.site,
20697
+ plateNumber: value.plateNumber,
20698
+ type: "whitelist" /* WHITELIST */,
20699
+ nric: value.nric,
20700
+ start: startString,
20701
+ end: endString,
20702
+ recNo: value.recNo
20703
+ };
20704
+ await addVehicle(vehiclePayload);
20705
+ } else {
20706
+ const dahuaPayload = {
20707
+ host,
20708
+ username,
20709
+ password,
20710
+ plateNumber: _plateNumber,
20711
+ recno: parsed.recNo,
20712
+ mode,
20713
+ start: startDahuaDate,
20714
+ end: endDahuaDate,
20715
+ owner: value.name ?? "",
20716
+ isOpenGate: site?.isOpenGate ?? true
20717
+ };
20718
+ const dahuaResponse = await _updatePlateNumber(dahuaPayload);
20719
+ if (dahuaResponse?.statusCode !== 200) {
20720
+ throw new BadRequestError96(
20721
+ `Failed to update plate number to ANPR ${"whitelist" /* WHITELIST */}`
20722
+ );
20723
+ }
20724
+ value.recNo = parsed.recNo;
20750
20725
  }
20751
- const responseData = dahuaResponse?.data?.toString("utf-8") ?? "";
20752
- value.recNo = responseData.split("=")[1]?.trim();
20753
- value.checkIn = startString;
20754
- value.expiredAt = endString;
20755
20726
  }
20756
20727
  const result = await _add(value, session);
20757
20728
  await session?.commitTransaction();
@@ -21085,7 +21056,6 @@ function useVisitorTransactionController() {
21085
21056
  }
21086
21057
  }
21087
21058
  async function inviteVisitor(req, res, next) {
21088
- const inviter = req.params.inviterId;
21089
21059
  const schema2 = Joi55.object({
21090
21060
  name: Joi55.string().required(),
21091
21061
  contact: Joi55.string().required(),
@@ -34118,7 +34088,7 @@ function useOccurrenceBookRepo() {
34118
34088
  date = "",
34119
34089
  status = ""
34120
34090
  }, session) {
34121
- page = page > 0 ? page - 1 : 0;
34091
+ page = page > 0 && !date ? page - 1 : 0;
34122
34092
  const _site = toObjectId12(site);
34123
34093
  const query = {
34124
34094
  site: _site,
@@ -37599,12 +37569,15 @@ function useIncidentReportRepo() {
37599
37569
  }
37600
37570
  if (dateFrom) {
37601
37571
  const [year, month, day] = dateFrom.split("-").map(Number);
37602
- const start = new Date(year, month - 1, day, 0, 0, 0, 0).toISOString();
37603
- const end = new Date(year, month - 1, day, 23, 59, 59, 999).toISOString();
37572
+ const offset = 8;
37573
+ const start = new Date(Date.UTC(year, month - 1, day, -offset, 0, 0, 0));
37574
+ const end = new Date(
37575
+ Date.UTC(year, month - 1, day, 23 - offset, 59, 59, 999)
37576
+ );
37604
37577
  dateExpr = {
37605
37578
  "incidentInformation.incidentTypeAndTime.dateOfIncident": {
37606
- $gte: start,
37607
- $lte: end
37579
+ $gte: start.toISOString(),
37580
+ $lte: end.toISOString()
37608
37581
  }
37609
37582
  };
37610
37583
  }
@@ -45500,12 +45473,6 @@ function useVerificationRepoV2() {
45500
45473
  err
45501
45474
  );
45502
45475
  });
45503
- const cacheKey = makeCacheKey64(namespace_collection, { _id });
45504
- delCache(cacheKey).then(() => {
45505
- logger175.info(`Cache deleted for key: ${cacheKey}`);
45506
- }).catch((err) => {
45507
- logger175.error(`Failed to delete cache for key: ${cacheKey}`, err);
45508
- });
45509
45476
  return result;
45510
45477
  } catch (error) {
45511
45478
  throw new InternalServerError68("Error updating verification status.");
@@ -45921,9 +45888,12 @@ function useVerificationControllerV2() {
45921
45888
  async function verify(req, res, next) {
45922
45889
  try {
45923
45890
  const schema2 = Joi126.object({ verificationCode: Joi126.string().required() });
45924
- const { error, value } = schema2.validate({
45925
- verificationCode: req.params.verificationCode
45926
- });
45891
+ const { error, value } = schema2.validate(
45892
+ {
45893
+ verificationCode: req.params.verificationCode
45894
+ },
45895
+ { abortEarly: false }
45896
+ );
45927
45897
  if (error) {
45928
45898
  const messages = error.details.map((d) => d.message).join(", ");
45929
45899
  logger177.log({ level: "error", message: messages });
@@ -45949,7 +45919,7 @@ function useVerificationControllerV2() {
45949
45919
  siteId: Joi126.string().hex().length(24).optional().allow("", null),
45950
45920
  siteName: Joi126.string().optional().allow("", null)
45951
45921
  });
45952
- const { error, value } = schema2.validate(req.body);
45922
+ const { error, value } = schema2.validate(req.body, { abortEarly: false });
45953
45923
  if (error) {
45954
45924
  const messages = error.details.map((d) => d.message).join(", ");
45955
45925
  logger177.log({ level: "error", message: messages });
@@ -45984,7 +45954,7 @@ function useVerificationControllerV2() {
45984
45954
  siteId: Joi126.string().hex().length(24).required(),
45985
45955
  siteName: Joi126.string().required()
45986
45956
  });
45987
- const { error, value } = schema2.validate(req.body);
45957
+ const { error, value } = schema2.validate(req.body, { abortEarly: false });
45988
45958
  if (error) {
45989
45959
  const messages = error.details.map((d) => d.message).join(", ");
45990
45960
  logger177.log({ level: "error", message: messages });
@@ -46010,7 +45980,7 @@ function useVerificationControllerV2() {
46010
45980
  const schema2 = Joi126.object({
46011
45981
  email: Joi126.string().email().lowercase().required()
46012
45982
  });
46013
- const { error, value } = schema2.validate(req.body);
45983
+ const { error, value } = schema2.validate(req.body, { abortEarly: false });
46014
45984
  if (error) {
46015
45985
  const messages = error.details.map((d) => d.message).join(", ");
46016
45986
  logger177.log({ level: "error", message: messages });
@@ -46040,7 +46010,7 @@ function useVerificationControllerV2() {
46040
46010
 
46041
46011
  // src/controllers/auth-v2.controller.ts
46042
46012
  import Joi127 from "joi";
46043
- import { BadRequestError as BadRequestError200, logger as logger179 } from "@7365admin1/node-server-utils";
46013
+ import { BadRequestError as BadRequestError201, logger as logger180 } from "@7365admin1/node-server-utils";
46044
46014
 
46045
46015
  // src/services/auth-v2.service.ts
46046
46016
  import {
@@ -46053,11 +46023,13 @@ import {
46053
46023
  import { v4 as uuidv42 } from "uuid";
46054
46024
 
46055
46025
  // src/repositories/user-v2.repo.ts
46026
+ import { ObjectId as ObjectId123 } from "mongodb";
46056
46027
  import {
46057
46028
  useAtlas as useAtlas113,
46058
46029
  InternalServerError as InternalServerError70,
46059
46030
  logger as logger178,
46060
46031
  BadRequestError as BadRequestError198,
46032
+ paginate as paginate58,
46061
46033
  NotFoundError as NotFoundError52,
46062
46034
  AppError as AppError27,
46063
46035
  useCache as useCache67,
@@ -46074,6 +46046,7 @@ function useUserRepoV2() {
46074
46046
  }
46075
46047
  const namespace_collection = "users";
46076
46048
  const collection = db.collection(namespace_collection);
46049
+ const { delNamespace, setCache, getCache, delCache } = useCache67(namespace_collection);
46077
46050
  async function createIndex() {
46078
46051
  try {
46079
46052
  await collection.createIndexes([{ key: { email: 1 } }]);
@@ -46083,10 +46056,7 @@ function useUserRepoV2() {
46083
46056
  }
46084
46057
  async function createTextIndex() {
46085
46058
  try {
46086
- await collection.createIndex({
46087
- name: "text",
46088
- email: "text"
46089
- });
46059
+ await collection.createIndex({ name: "text", email: "text" });
46090
46060
  } catch (error) {
46091
46061
  throw new InternalServerError70("Failed to create text index on user.");
46092
46062
  }
@@ -46101,24 +46071,22 @@ function useUserRepoV2() {
46101
46071
  throw new InternalServerError70("Failed to create unique index on user.");
46102
46072
  }
46103
46073
  }
46104
- const { delNamespace, setCache, getCache, delCache } = useCache67(namespace_collection);
46105
46074
  async function createUser(value, session) {
46106
46075
  try {
46107
46076
  value = MUser(value);
46108
46077
  const res = await collection.insertOne(value, { session });
46109
- delNamespace().then(() => {
46110
- logger178.info(`Cache cleared for namespace: ${namespace_collection}`);
46111
- }).catch((err) => {
46112
- logger178.error(
46078
+ delNamespace().then(
46079
+ () => logger178.info(`Cache cleared for namespace: ${namespace_collection}`)
46080
+ ).catch(
46081
+ (err) => logger178.error(
46113
46082
  `Failed to clear cache for namespace: ${namespace_collection}`,
46114
46083
  err
46115
- );
46116
- });
46084
+ )
46085
+ );
46117
46086
  return res.insertedId;
46118
46087
  } catch (error) {
46119
46088
  logger178.log({ level: "error", message: `${error}` });
46120
- const isDuplicated = error.message.includes("duplicate");
46121
- if (isDuplicated) {
46089
+ if (error.message.includes("duplicate")) {
46122
46090
  throw new BadRequestError198("User already exists.");
46123
46091
  }
46124
46092
  throw error;
@@ -46135,11 +46103,9 @@ function useUserRepoV2() {
46135
46103
  const data = await collection.findOne({
46136
46104
  email: { $regex: `^${email}$`, $options: "i" }
46137
46105
  });
46138
- setCache(cacheKey, data, 15 * 60).then(() => {
46139
- logger178.info(`Cache set for key: ${cacheKey}`);
46140
- }).catch((err) => {
46141
- logger178.error(`Failed to set cache for key: ${cacheKey}`, err);
46142
- });
46106
+ setCache(cacheKey, data, 15 * 60).then(() => logger178.info(`Cache set for key: ${cacheKey}`)).catch(
46107
+ (err) => logger178.error(`Failed to set cache for key: ${cacheKey}`, err)
46108
+ );
46143
46109
  return data;
46144
46110
  } catch (error) {
46145
46111
  throw new InternalServerError70("Failed to get user by email.");
@@ -46147,26 +46113,22 @@ function useUserRepoV2() {
46147
46113
  }
46148
46114
  async function getUserByEmailStatus(email) {
46149
46115
  try {
46150
- const cacheOptions = {
46116
+ const cacheKey = makeCacheKey65(namespace_collection, {
46151
46117
  email,
46152
46118
  status: "complete" /* COMPLETE */
46153
- };
46154
- const cacheKey = makeCacheKey65(namespace_collection, cacheOptions);
46119
+ });
46155
46120
  const cachedData = await getCache(cacheKey);
46156
46121
  if (cachedData) {
46157
46122
  logger178.info(`Cache hit for key: ${cacheKey}`);
46158
46123
  return cachedData;
46159
46124
  }
46160
- const query = {
46125
+ const data = await collection.findOne({
46161
46126
  email: { $regex: `^${email}$`, $options: "i" },
46162
46127
  status: "complete" /* COMPLETE */
46163
- };
46164
- const data = await collection.findOne(query);
46165
- setCache(cacheKey, data, 15 * 60).then(() => {
46166
- logger178.info(`Cache set for key: ${cacheKey}`);
46167
- }).catch((err) => {
46168
- logger178.error(`Failed to set cache for key: ${cacheKey}`, err);
46169
46128
  });
46129
+ setCache(cacheKey, data, 15 * 60).then(() => logger178.info(`Cache set for key: ${cacheKey}`)).catch(
46130
+ (err) => logger178.error(`Failed to set cache for key: ${cacheKey}`, err)
46131
+ );
46170
46132
  return data;
46171
46133
  } catch (error) {
46172
46134
  throw new InternalServerError70("Failed to get user by email.");
@@ -46189,17 +46151,10 @@ function useUserRepoV2() {
46189
46151
  let: { userOrgId: "$defaultOrg" },
46190
46152
  pipeline: [
46191
46153
  {
46192
- $match: {
46193
- $expr: { $eq: ["$orgId", "$$userOrgId"] }
46194
- }
46154
+ $match: { $expr: { $eq: ["$orgId", "$$userOrgId"] } }
46195
46155
  },
46196
46156
  {
46197
- $project: {
46198
- _id: 1,
46199
- name: 1,
46200
- type: 1,
46201
- siteId: 1
46202
- }
46157
+ $project: { _id: 1, name: 1, type: 1, siteId: 1 }
46203
46158
  }
46204
46159
  ],
46205
46160
  as: "serviceProviders"
@@ -46207,9 +46162,117 @@ function useUserRepoV2() {
46207
46162
  }
46208
46163
  ]).toArray();
46209
46164
  const data = results.length > 0 ? results[0] : null;
46210
- if (!data) {
46165
+ if (!data)
46211
46166
  throw new NotFoundError52("User not found.");
46167
+ setCache(cacheKey, data, 15 * 60).then(() => logger178.info(`Cache set for key: ${cacheKey}`)).catch(
46168
+ (err) => logger178.error(`Failed to set cache for key: ${cacheKey}`, err)
46169
+ );
46170
+ return data;
46171
+ } catch (error) {
46172
+ if (error instanceof AppError27)
46173
+ throw error;
46174
+ throw new InternalServerError70("Failed to get user by id.");
46175
+ }
46176
+ }
46177
+ async function getUserByReferralCode(referralCode) {
46178
+ try {
46179
+ const cacheKey = makeCacheKey65(namespace_collection, { referralCode });
46180
+ const cachedData = await getCache(cacheKey);
46181
+ if (cachedData) {
46182
+ logger178.info(`Cache hit for key: ${cacheKey}`);
46183
+ return cachedData;
46184
+ }
46185
+ const data = await collection.findOne({ referralCode });
46186
+ setCache(cacheKey, data, 15 * 60).then(() => logger178.info(`Cache set for key: ${cacheKey}`)).catch(
46187
+ (err) => logger178.error(`Failed to set cache for key: ${cacheKey}`, err)
46188
+ );
46189
+ return data;
46190
+ } catch (error) {
46191
+ throw new InternalServerError70("Failed to get user by referral code.");
46192
+ }
46193
+ }
46194
+ async function getByEmailApp(email, app) {
46195
+ try {
46196
+ const cacheKey = makeCacheKey65(namespace_collection, { email, app });
46197
+ const cachedData = await getCache(cacheKey);
46198
+ if (cachedData) {
46199
+ logger178.info(`Cache hit for key: ${cacheKey}`);
46200
+ return cachedData;
46212
46201
  }
46202
+ const data = await collection.findOne({
46203
+ email,
46204
+ "roles.app": app
46205
+ });
46206
+ setCache(cacheKey, data, 15 * 60).then(() => logger178.info(`Cache set for key: ${cacheKey}`)).catch(
46207
+ (err) => logger178.error(`Failed to set cache for key: ${cacheKey}`, err)
46208
+ );
46209
+ return data;
46210
+ } catch (error) {
46211
+ throw new InternalServerError70("Failed to get user by email and app.");
46212
+ }
46213
+ }
46214
+ async function getUsersByOrgId({
46215
+ organization = "",
46216
+ search = "",
46217
+ page = 1,
46218
+ limit = 10,
46219
+ sort = {},
46220
+ type = "",
46221
+ status = "active"
46222
+ }) {
46223
+ page = page > 0 ? page - 1 : 0;
46224
+ const query = { status };
46225
+ const cacheOptions = { status };
46226
+ sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
46227
+ cacheOptions.sort = JSON.stringify(sort);
46228
+ if (search) {
46229
+ query.$text = { $search: search };
46230
+ cacheOptions.search = search;
46231
+ }
46232
+ if (type) {
46233
+ query.type = type;
46234
+ cacheOptions.type = type;
46235
+ }
46236
+ if (organization) {
46237
+ try {
46238
+ query.defaultOrg = new ObjectId123(organization);
46239
+ cacheOptions.organization = organization.toString();
46240
+ } catch (error) {
46241
+ throw new BadRequestError198("Invalid organization ID format.");
46242
+ }
46243
+ }
46244
+ delNamespace().then(() => {
46245
+ logger178.info(`Cache cleared for namespace: ${namespace_collection}`);
46246
+ }).catch((err) => {
46247
+ logger178.error(
46248
+ `Failed to clear cache for namespace: ${namespace_collection}`,
46249
+ err
46250
+ );
46251
+ });
46252
+ const cacheKey = makeCacheKey65(namespace_collection, cacheOptions);
46253
+ const cachedData = await getCache(cacheKey);
46254
+ if (cachedData) {
46255
+ logger178.info(`Cache hit for key: ${cacheKey}`);
46256
+ return cachedData;
46257
+ }
46258
+ try {
46259
+ const items = await collection.aggregate([
46260
+ { $match: query },
46261
+ { $sort: sort },
46262
+ { $skip: page * limit },
46263
+ { $limit: limit },
46264
+ {
46265
+ $project: {
46266
+ _id: 1,
46267
+ name: 1,
46268
+ email: 1,
46269
+ type: 1,
46270
+ status: 1
46271
+ }
46272
+ }
46273
+ ]).toArray();
46274
+ const length = await collection.countDocuments(query);
46275
+ const data = paginate58(items, page, limit, length);
46213
46276
  setCache(cacheKey, data, 15 * 60).then(() => {
46214
46277
  logger178.info(`Cache set for key: ${cacheKey}`);
46215
46278
  }).catch((err) => {
@@ -46217,12 +46280,197 @@ function useUserRepoV2() {
46217
46280
  });
46218
46281
  return data;
46219
46282
  } catch (error) {
46220
- if (error instanceof AppError27) {
46283
+ logger178.log({ level: "error", message: `${error}` });
46284
+ throw error;
46285
+ }
46286
+ }
46287
+ async function getUsers({
46288
+ search = "",
46289
+ page = 1,
46290
+ limit = 10,
46291
+ sort = {},
46292
+ type = "",
46293
+ status = "active"
46294
+ }) {
46295
+ page = page > 0 ? page - 1 : 0;
46296
+ const query = { status };
46297
+ const cacheOptions = { status };
46298
+ sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
46299
+ cacheOptions.sort = JSON.stringify(sort);
46300
+ if (search) {
46301
+ query.$text = { $search: search };
46302
+ cacheOptions.search = search;
46303
+ }
46304
+ if (type) {
46305
+ query.type = type;
46306
+ cacheOptions.type = type;
46307
+ }
46308
+ delNamespace().then(
46309
+ () => logger178.info(`Cache cleared for namespace: ${namespace_collection}`)
46310
+ ).catch(
46311
+ (err) => logger178.error(
46312
+ `Failed to clear cache for namespace: ${namespace_collection}`,
46313
+ err
46314
+ )
46315
+ );
46316
+ const cacheKey = makeCacheKey65(namespace_collection, cacheOptions);
46317
+ const cachedData = await getCache(cacheKey);
46318
+ if (cachedData) {
46319
+ logger178.info(`Cache hit for key: ${cacheKey}`);
46320
+ return cachedData;
46321
+ }
46322
+ try {
46323
+ const items = await collection.aggregate([
46324
+ { $match: query },
46325
+ { $sort: sort },
46326
+ { $skip: page * limit },
46327
+ { $limit: limit },
46328
+ { $project: { _id: 1, name: 1, email: 1, type: 1, status: 1 } }
46329
+ ]).toArray();
46330
+ const length = await collection.countDocuments(query);
46331
+ const data = paginate58(items, page, limit, length);
46332
+ setCache(cacheKey, data, 15 * 60).then(() => logger178.info(`Cache set for key: ${cacheKey}`)).catch(
46333
+ (err) => logger178.error(`Failed to set cache for key: ${cacheKey}`, err)
46334
+ );
46335
+ return data;
46336
+ } catch (error) {
46337
+ logger178.log({ level: "error", message: `${error}` });
46338
+ throw error;
46339
+ }
46340
+ }
46341
+ async function updatePasswordById({ _id, password }, session) {
46342
+ const cacheKey = makeCacheKey65(namespace_collection, { _id });
46343
+ _id = toObjectId18(_id);
46344
+ try {
46345
+ const result = await collection.updateOne(
46346
+ { _id },
46347
+ { $set: { password, updatedAt: (/* @__PURE__ */ new Date()).toISOString() } },
46348
+ { session }
46349
+ );
46350
+ delCache(cacheKey).then(() => {
46351
+ logger178.info(`Cache deleted for key: ${cacheKey}`);
46352
+ }).catch((err) => {
46353
+ logger178.error(`Failed to delete cache for key: ${cacheKey}`, err);
46354
+ });
46355
+ return result;
46356
+ } catch (error) {
46357
+ throw new InternalServerError70("Failed to update user password.");
46358
+ }
46359
+ }
46360
+ async function updateUserFieldById({ _id, field, value } = {}, session) {
46361
+ const allowedFields = [
46362
+ "name",
46363
+ "email",
46364
+ "contact",
46365
+ "nric",
46366
+ "dateOfBirth",
46367
+ "profile",
46368
+ "gender",
46369
+ "defaultOrg"
46370
+ ];
46371
+ if (!allowedFields.includes(field)) {
46372
+ throw new BadRequestError198(
46373
+ `Field "${field}" is not allowed to be updated.`
46374
+ );
46375
+ }
46376
+ try {
46377
+ _id = new ObjectId123(_id);
46378
+ } catch (error) {
46379
+ throw new BadRequestError198("Invalid ID.");
46380
+ }
46381
+ if (field === "defaultOrg") {
46382
+ try {
46383
+ value = new ObjectId123(value);
46384
+ } catch (error) {
46385
+ throw new BadRequestError198("Invalid organization ID.");
46386
+ }
46387
+ }
46388
+ if (field === "name") {
46389
+ try {
46390
+ await Promise.all([
46391
+ updateFeedbackCreatedByName(_id, value, session),
46392
+ updateWorkOrderCreatedByName(_id, value, session),
46393
+ updateUserNameBySignatureId(_id, value, session)
46394
+ ]);
46395
+ } catch (error) {
46221
46396
  throw error;
46222
- } else {
46223
- throw new InternalServerError70("Failed to get user by email.");
46224
46397
  }
46225
46398
  }
46399
+ try {
46400
+ await collection.updateOne(
46401
+ { _id },
46402
+ { $set: { [field]: value, updatedAt: (/* @__PURE__ */ new Date()).toISOString() } },
46403
+ // Dynamically set the field
46404
+ { session }
46405
+ );
46406
+ const cacheKey = makeCacheKey65(namespace_collection, { _id });
46407
+ delCache(cacheKey).then(() => {
46408
+ logger178.info(`Cache deleted for key: ${cacheKey}`);
46409
+ }).catch((err) => {
46410
+ logger178.error(`Failed to delete cache for key: ${cacheKey}`, err);
46411
+ });
46412
+ return `Successfully updated user ${field}.`;
46413
+ } catch (error) {
46414
+ throw new InternalServerError70(`Failed to update user ${field}.`);
46415
+ }
46416
+ }
46417
+ async function updateBirthday({
46418
+ _id,
46419
+ month,
46420
+ day,
46421
+ year
46422
+ }, session) {
46423
+ try {
46424
+ _id = new ObjectId123(_id);
46425
+ } catch (error) {
46426
+ throw new BadRequestError198("Invalid user ID format.");
46427
+ }
46428
+ try {
46429
+ await collection.updateOne(
46430
+ { _id },
46431
+ {
46432
+ $set: {
46433
+ birthMonth: month,
46434
+ birthDay: day,
46435
+ birthYear: year,
46436
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
46437
+ }
46438
+ },
46439
+ { session }
46440
+ );
46441
+ const cacheKey = makeCacheKey65(namespace_collection, { _id });
46442
+ delCache(cacheKey).then(() => {
46443
+ logger178.info(`Cache deleted for key: ${cacheKey}`);
46444
+ }).catch((err) => {
46445
+ logger178.error(`Failed to delete cache for key: ${cacheKey}`, err);
46446
+ });
46447
+ return "Successfully updated user birthday.";
46448
+ } catch (error) {
46449
+ throw new InternalServerError70("Failed to update user birthday.");
46450
+ }
46451
+ }
46452
+ async function updatePassword({ _id, password }, session) {
46453
+ try {
46454
+ _id = new ObjectId123(_id);
46455
+ } catch (error) {
46456
+ throw new BadRequestError198("Invalid user ID format.");
46457
+ }
46458
+ try {
46459
+ const result = await collection.updateOne(
46460
+ { _id },
46461
+ { $set: { password, updatedAt: (/* @__PURE__ */ new Date()).toISOString() } },
46462
+ { session }
46463
+ );
46464
+ const cacheKey = makeCacheKey65(namespace_collection, { _id });
46465
+ delCache(cacheKey).then(() => {
46466
+ logger178.info(`Cache deleted for key: ${cacheKey}`);
46467
+ }).catch((err) => {
46468
+ logger178.error(`Failed to delete cache for key: ${cacheKey}`, err);
46469
+ });
46470
+ return result;
46471
+ } catch (error) {
46472
+ throw new InternalServerError70("Failed to update user password.");
46473
+ }
46226
46474
  }
46227
46475
  return {
46228
46476
  createIndex,
@@ -46231,7 +46479,13 @@ function useUserRepoV2() {
46231
46479
  createUser,
46232
46480
  getUserByEmail,
46233
46481
  getUserByEmailStatus,
46234
- getUserById
46482
+ getUserById,
46483
+ getUsers,
46484
+ getUsersByOrgId,
46485
+ updatePasswordById,
46486
+ updateUserFieldById,
46487
+ updateBirthday,
46488
+ updatePassword
46235
46489
  };
46236
46490
  }
46237
46491
 
@@ -46298,10 +46552,220 @@ function useAuthServiceV2() {
46298
46552
  };
46299
46553
  }
46300
46554
 
46555
+ // src/services/user-v2.service.ts
46556
+ import {
46557
+ BadRequestError as BadRequestError200,
46558
+ comparePassword as comparePassword4,
46559
+ hashPassword as hashPassword5,
46560
+ InternalServerError as InternalServerError72,
46561
+ NotFoundError as NotFoundError54,
46562
+ useAtlas as useAtlas114,
46563
+ useS3 as useS33
46564
+ } from "@7365admin1/node-server-utils";
46565
+ import "multer";
46566
+ function useUserServiceV2() {
46567
+ const {
46568
+ createUser: _createUser,
46569
+ getUserByEmail: _getUserByEmail,
46570
+ updatePasswordById: _updatePasswordById,
46571
+ updateUserFieldById: _updateUserFieldById,
46572
+ getUserById,
46573
+ updatePassword
46574
+ } = useUserRepoV2();
46575
+ const { getRoleByName, addRole } = useRoleRepo();
46576
+ const { add: addMember } = useMemberRepo();
46577
+ const { getById: getOrgById } = useOrgRepo();
46578
+ const { getSiteById } = useSiteRepo();
46579
+ const {
46580
+ getVerificationById: _getVerificationById,
46581
+ updateVerificationStatusById: _updateVerificationStatusById
46582
+ } = useVerificationRepoV2();
46583
+ const { verify: _verify } = useVerificationServiceV2();
46584
+ const { createFile, deleteFileById } = useFileRepo();
46585
+ async function createUserBySignUp({
46586
+ id = "",
46587
+ name = ""
46588
+ }) {
46589
+ const session = useAtlas114.getClient()?.startSession();
46590
+ session?.startTransaction();
46591
+ try {
46592
+ const signUp = await _getVerificationById(id);
46593
+ if (!signUp)
46594
+ throw new BadRequestError200("Invalid sign up link.");
46595
+ if (signUp.status === "complete" /* COMPLETE */)
46596
+ throw new BadRequestError200(
46597
+ "You have already an account created using this link."
46598
+ );
46599
+ const expired = signUp.expireAt < (/* @__PURE__ */ new Date()).toISOString();
46600
+ if (signUp.status === "expired" || expired)
46601
+ throw new BadRequestError200("Sign up link expired.");
46602
+ const email = signUp.email;
46603
+ const _user = await _getUserByEmail(email);
46604
+ if (_user)
46605
+ throw new BadRequestError200(`User already exists: ${email}.`);
46606
+ let org = null;
46607
+ if (signUp.metadata?.org) {
46608
+ org = await getOrgById(signUp.metadata.org);
46609
+ if (!org)
46610
+ signUp.metadata.org = "";
46611
+ }
46612
+ if (signUp.metadata?.siteId)
46613
+ await getSiteById(signUp.metadata?.siteId);
46614
+ const user = {
46615
+ email,
46616
+ password: signUp.metadata?.password,
46617
+ name,
46618
+ defaultOrg: org?._id?.toString() || ""
46619
+ };
46620
+ const userId = await _createUser(user, session);
46621
+ if (org?._id) {
46622
+ await addMember(
46623
+ {
46624
+ org: org?._id?.toString() || "",
46625
+ orgName: org?.name || "",
46626
+ user: userId.toString(),
46627
+ name,
46628
+ role: signUp.metadata?.role?.toString() || "",
46629
+ type: signUp.metadata?.app ?? "organization",
46630
+ siteId: signUp.metadata?.siteId?.toString() || "",
46631
+ siteName: signUp.metadata?.siteName || ""
46632
+ },
46633
+ session
46634
+ );
46635
+ }
46636
+ await _updateVerificationStatusById(
46637
+ id,
46638
+ "complete" /* COMPLETE */,
46639
+ session
46640
+ );
46641
+ await session?.commitTransaction();
46642
+ return userId;
46643
+ } catch (error) {
46644
+ await session?.abortTransaction();
46645
+ throw error;
46646
+ } finally {
46647
+ session?.endSession();
46648
+ }
46649
+ }
46650
+ async function resetPassword(id, newPassword, passwordConfirmation) {
46651
+ if (newPassword !== passwordConfirmation) {
46652
+ throw new BadRequestError200("Passwords do not match.");
46653
+ }
46654
+ let hashedPassword;
46655
+ const session = useAtlas114.getClient()?.startSession();
46656
+ session?.startTransaction();
46657
+ try {
46658
+ hashedPassword = await hashPassword5(newPassword);
46659
+ } catch (error) {
46660
+ throw new InternalServerError72(`Error hashing password: ${error}`);
46661
+ }
46662
+ try {
46663
+ const otpDoc = await _getVerificationById(id);
46664
+ if (!otpDoc) {
46665
+ throw new NotFoundError54("You are using an invalid reset link.");
46666
+ }
46667
+ if (otpDoc.status === "complete" /* COMPLETE */) {
46668
+ throw new BadRequestError200("This link has already been invalidated.");
46669
+ }
46670
+ const user = await _getUserByEmail(otpDoc.email);
46671
+ if (!user) {
46672
+ throw new NotFoundError54("User not found.");
46673
+ }
46674
+ if (!user._id) {
46675
+ throw new InternalServerError72("Invalid user ID.");
46676
+ }
46677
+ await Promise.all([
46678
+ _updateVerificationStatusById(id, "complete" /* COMPLETE */, session),
46679
+ _updatePasswordById(
46680
+ { _id: user._id.toString(), password: hashedPassword },
46681
+ session
46682
+ )
46683
+ ]);
46684
+ await session?.commitTransaction();
46685
+ return "Successfully reset password.";
46686
+ } catch (error) {
46687
+ await session?.abortTransaction();
46688
+ throw error;
46689
+ } finally {
46690
+ session?.endSession();
46691
+ }
46692
+ }
46693
+ const s3 = new useS33({
46694
+ accessKeyId: SPACES_ACCESS_KEY,
46695
+ secretAccessKey: SPACES_SECRET_KEY,
46696
+ endpoint: SPACES_ENDPOINT,
46697
+ region: SPACES_REGION,
46698
+ bucket: SPACES_BUCKET,
46699
+ forcePathStyle: false
46700
+ });
46701
+ async function updateUserProfile({
46702
+ file,
46703
+ user,
46704
+ previousProfile
46705
+ }) {
46706
+ const session = useAtlas114.getClient()?.startSession();
46707
+ session?.startTransaction();
46708
+ const _file = {
46709
+ name: file.originalname,
46710
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
46711
+ };
46712
+ try {
46713
+ const id = await createFile(_file, session);
46714
+ await s3.uploadObject({
46715
+ key: id,
46716
+ body: file.buffer,
46717
+ contentType: file.mimetype
46718
+ });
46719
+ if (previousProfile) {
46720
+ await deleteFileById(previousProfile, session);
46721
+ await s3.deleteObject(previousProfile);
46722
+ }
46723
+ await _updateUserFieldById(
46724
+ { _id: user, field: "profile", value: id },
46725
+ session
46726
+ );
46727
+ await session?.commitTransaction();
46728
+ return id;
46729
+ } catch (error) {
46730
+ await session?.abortTransaction();
46731
+ throw error;
46732
+ } finally {
46733
+ session?.endSession();
46734
+ }
46735
+ }
46736
+ async function updatePasswordById(id, currentPassword, newPassword, passwordConfirmation) {
46737
+ let hashedPassword;
46738
+ const user = await getUserById(id);
46739
+ const isPasswordValid = await comparePassword4(
46740
+ currentPassword,
46741
+ user.password
46742
+ );
46743
+ if (!isPasswordValid)
46744
+ throw new BadRequestError200("Invalid current password.");
46745
+ if (newPassword !== passwordConfirmation)
46746
+ throw new BadRequestError200("Passwords do not match.");
46747
+ try {
46748
+ hashedPassword = await hashPassword5(newPassword);
46749
+ if (!hashedPassword)
46750
+ throw new InternalServerError72("Error hashing password.");
46751
+ return await updatePassword({ _id: id, password: hashedPassword });
46752
+ } catch (error) {
46753
+ throw error;
46754
+ }
46755
+ }
46756
+ return {
46757
+ createUserBySignUp,
46758
+ resetPassword,
46759
+ updateUserProfile,
46760
+ updatePasswordById
46761
+ };
46762
+ }
46763
+
46301
46764
  // src/controllers/auth-v2.controller.ts
46302
46765
  function useAuthControllerV2() {
46303
46766
  const { signUp: _signUp } = useVerificationServiceV2();
46304
46767
  const { login: _login, logout: _logout } = useAuthServiceV2();
46768
+ const { resetPassword: _resetPassword } = useUserServiceV2();
46305
46769
  async function signUp(req, res, next) {
46306
46770
  try {
46307
46771
  const validation = Joi127.object({
@@ -46315,8 +46779,8 @@ function useAuthControllerV2() {
46315
46779
  });
46316
46780
  if (error) {
46317
46781
  const messages = error.details.map((d) => d.message);
46318
- logger179.log({ level: "error", message: messages.join(", ") });
46319
- next(new BadRequestError200(messages.join(", ")));
46782
+ logger180.log({ level: "error", message: messages.join(", ") });
46783
+ next(new BadRequestError201(messages.join(", ")));
46320
46784
  return;
46321
46785
  }
46322
46786
  const { email, password, country, orgName } = value;
@@ -46332,7 +46796,7 @@ function useAuthControllerV2() {
46332
46796
  return;
46333
46797
  } catch (error) {
46334
46798
  console.log(error);
46335
- logger179.log({ level: "error", message: error.message });
46799
+ logger180.log({ level: "error", message: error.message });
46336
46800
  next(error);
46337
46801
  return;
46338
46802
  }
@@ -46350,8 +46814,8 @@ function useAuthControllerV2() {
46350
46814
  });
46351
46815
  if (error) {
46352
46816
  const messages = error.details.map((d) => d.message);
46353
- logger179.log({ level: "error", message: messages.join(", ") });
46354
- next(new BadRequestError200(messages.join(", ")));
46817
+ logger180.log({ level: "error", message: messages.join(", ") });
46818
+ next(new BadRequestError201(messages.join(", ")));
46355
46819
  return;
46356
46820
  }
46357
46821
  const session = await _login(value);
@@ -46363,7 +46827,7 @@ function useAuthControllerV2() {
46363
46827
  res.cookie("sid", session.sid, cookieOptions).cookie("user", session.user, cookieOptions).json(session);
46364
46828
  return;
46365
46829
  } catch (error) {
46366
- logger179.log({ level: "error", message: error.message });
46830
+ logger180.log({ level: "error", message: error.message });
46367
46831
  next(error);
46368
46832
  return;
46369
46833
  }
@@ -46371,7 +46835,7 @@ function useAuthControllerV2() {
46371
46835
  async function logout(req, res, next) {
46372
46836
  const sid = req.headers["authorization"] ?? "";
46373
46837
  if (!sid) {
46374
- next(new BadRequestError200("Session ID is required"));
46838
+ next(new BadRequestError201("Session ID is required"));
46375
46839
  return;
46376
46840
  }
46377
46841
  try {
@@ -46379,130 +46843,170 @@ function useAuthControllerV2() {
46379
46843
  res.json({ message: "Logged out successfully" });
46380
46844
  return;
46381
46845
  } catch (error) {
46382
- logger179.log({ level: "error", message: error.message });
46846
+ logger180.log({ level: "error", message: error.message });
46383
46847
  next(error);
46384
46848
  return;
46385
46849
  }
46386
46850
  }
46387
- return {
46388
- signUp,
46389
- login,
46390
- logout
46391
- };
46392
- }
46393
-
46394
- // src/services/user-v2.service.ts
46395
- import {
46396
- BadRequestError as BadRequestError201,
46397
- useAtlas as useAtlas114
46398
- } from "@7365admin1/node-server-utils";
46399
- import "multer";
46400
- function useUserServiceV2() {
46401
- const { createUser: _createUser, getUserByEmail } = useUserRepoV2();
46402
- const { getRoleByName, addRole } = useRoleRepo();
46403
- const { add: addMember } = useMemberRepo();
46404
- const { getById: getOrgById } = useOrgRepo();
46405
- const { getSiteById } = useSiteRepo();
46406
- const {
46407
- getVerificationById: _getVerificationById,
46408
- updateVerificationStatusById: _updateVerificationStatusById
46409
- } = useVerificationRepoV2();
46410
- const { verify } = useVerificationService();
46411
- const { createFile, deleteFileById } = useFileRepo();
46412
- async function createUserBySignUp({
46413
- id = "",
46414
- name = ""
46415
- }) {
46416
- const session = useAtlas114.getClient()?.startSession();
46417
- session?.startTransaction();
46851
+ async function resetPassword(req, res, next) {
46852
+ const validation = Joi127.object({
46853
+ otp: Joi127.string().hex().required(),
46854
+ newPassword: Joi127.string().required().min(8),
46855
+ passwordConfirmation: Joi127.string().required().min(8)
46856
+ });
46857
+ const { error, value } = validation.validate(req.body, {
46858
+ abortEarly: false
46859
+ });
46860
+ if (error) {
46861
+ const messages = error.details.map((d) => d.message);
46862
+ logger180.log({ level: "error", message: messages.join(", ") });
46863
+ next(new BadRequestError201(messages.join(", ")));
46864
+ return;
46865
+ }
46866
+ const { otp, newPassword, passwordConfirmation } = value;
46418
46867
  try {
46419
- const signUp = await _getVerificationById(id);
46420
- if (!signUp)
46421
- throw new BadRequestError201("Invalid sign up link.");
46422
- if (signUp.status === "complete")
46423
- throw new BadRequestError201(
46424
- "You have already an account created using this link."
46425
- );
46426
- const expired = signUp.expireAt < (/* @__PURE__ */ new Date()).toISOString();
46427
- if (signUp.status === "expired" || expired)
46428
- throw new BadRequestError201("Sign up link expired.");
46429
- const email = signUp.email;
46430
- const _user = await getUserByEmail(email);
46431
- if (_user)
46432
- throw new BadRequestError201(`User already exists: ${email}.`);
46433
- let org = null;
46434
- if (signUp.metadata?.org) {
46435
- org = await getOrgById(signUp.metadata.org);
46436
- if (!org)
46437
- signUp.metadata.org = "";
46438
- }
46439
- if (signUp.metadata?.siteId)
46440
- await getSiteById(signUp.metadata?.siteId);
46441
- const user = {
46442
- email,
46443
- password: signUp.metadata?.password,
46444
- name,
46445
- defaultOrg: org?._id?.toString() || ""
46446
- };
46447
- const userId = await _createUser(user, session);
46448
- if (org?._id) {
46449
- await addMember(
46450
- {
46451
- org: org?._id?.toString() || "",
46452
- orgName: org?.name || "",
46453
- user: userId.toString(),
46454
- name,
46455
- role: signUp.metadata?.role?.toString() || "",
46456
- type: signUp.metadata?.app ?? "organization",
46457
- siteId: signUp.metadata?.siteId?.toString() || "",
46458
- siteName: signUp.metadata?.siteName || ""
46459
- },
46460
- session
46461
- );
46462
- }
46463
- await _updateVerificationStatusById(
46464
- id,
46465
- "complete" /* COMPLETE */,
46466
- session
46868
+ const message = await _resetPassword(
46869
+ otp,
46870
+ newPassword,
46871
+ passwordConfirmation
46467
46872
  );
46468
- await session?.commitTransaction();
46469
- return userId;
46470
- } catch (error) {
46471
- await session?.abortTransaction();
46472
- throw error;
46473
- } finally {
46474
- session?.endSession();
46873
+ res.json({ message });
46874
+ return;
46875
+ } catch (error2) {
46876
+ logger180.log({ level: "error", message: error2.message });
46877
+ next(error2);
46878
+ return;
46475
46879
  }
46476
46880
  }
46477
46881
  return {
46478
- createUserBySignUp
46882
+ signUp,
46883
+ login,
46884
+ logout,
46885
+ resetPassword
46479
46886
  };
46480
46887
  }
46481
46888
 
46482
46889
  // src/controllers/user-v2.controller.ts
46483
46890
  import Joi128 from "joi";
46891
+ import "multer";
46484
46892
  import { BadRequestError as BadRequestError202, logger as logger181 } from "@7365admin1/node-server-utils";
46485
46893
  function useUserControllerV2() {
46486
- const { createUserBySignUp: _createUserBySignUp } = useUserServiceV2();
46894
+ const {
46895
+ updateBirthday: _updateBirthday,
46896
+ getUserById: _getUserById,
46897
+ getUserByEmail: _getUserByEmail,
46898
+ getUserById: _getById,
46899
+ getUsers: _getUsers,
46900
+ getUsersByOrgId: _getUsersByOrgId,
46901
+ updateUserFieldById: _updateUserFieldById
46902
+ } = useUserRepoV2();
46903
+ const { createUserBySignUp, updateUserProfile: _updateUserProfile, updatePasswordById: _updatePasswordById } = useUserServiceV2();
46904
+ function rejectValidation(error, next) {
46905
+ const message = error.details.map((d) => d.message).join(", ");
46906
+ logger181.log({ level: "error", message });
46907
+ next(new BadRequestError202(message));
46908
+ }
46909
+ async function getById(req, res, next) {
46910
+ const validation = Joi128.string().hex().required();
46911
+ const _id = req.params.id;
46912
+ const { error, value } = validation.validate(_id);
46913
+ if (error) {
46914
+ logger181.log({ level: "error", message: `${error.message}` });
46915
+ next(new BadRequestError202(error.message));
46916
+ return;
46917
+ }
46918
+ try {
46919
+ const user = await _getById(value);
46920
+ res.json(user);
46921
+ return;
46922
+ } catch (error2) {
46923
+ logger181.log({ level: "error", message: `${error2.message}` });
46924
+ next(error2);
46925
+ return;
46926
+ }
46927
+ }
46928
+ async function getByEmail(req, res, next) {
46929
+ const { error, value } = Joi128.string().email().required().validate(req.params.email);
46930
+ if (error)
46931
+ return rejectValidation(error, next);
46932
+ try {
46933
+ const user = await _getUserByEmail(value);
46934
+ res.json(user);
46935
+ return;
46936
+ } catch (err) {
46937
+ logger181.log({ level: "error", message: `${err.message}` });
46938
+ next(err);
46939
+ return;
46940
+ }
46941
+ }
46942
+ async function getUsers(req, res, next) {
46943
+ const { search = "", page = 1, limit = 10, sort = {}, type = "", status = "active" } = req.query;
46944
+ const { error, value } = Joi128.object({
46945
+ search: Joi128.string().optional().allow("", null),
46946
+ page: Joi128.number().integer().min(1).allow("", null).default(1),
46947
+ limit: Joi128.number().integer().min(1).allow("", null).default(10),
46948
+ sort: Joi128.object().optional().allow("", null).default({}),
46949
+ type: Joi128.string().optional().allow("", null).default(""),
46950
+ status: Joi128.string().optional().allow("", null).default("active" /* ACTIVE */)
46951
+ }).validate({ search, page, limit, sort, type, status });
46952
+ if (error)
46953
+ return rejectValidation(error, next);
46954
+ try {
46955
+ const users = await _getUsers({
46956
+ search: value.search ?? "",
46957
+ page: value.page,
46958
+ limit: value.limit,
46959
+ sort: value.sort,
46960
+ type: value.type,
46961
+ status: value.status
46962
+ });
46963
+ res.json(users);
46964
+ return;
46965
+ } catch (err) {
46966
+ next(err);
46967
+ }
46968
+ }
46969
+ async function getUsersByOrgId(req, res, next) {
46970
+ const { search, page, status, organization } = req.query;
46971
+ const { error, value } = Joi128.object({
46972
+ search: Joi128.string().optional().allow("", null),
46973
+ page: Joi128.number().integer().min(1).allow("", null).default(1),
46974
+ status: Joi128.string().required(),
46975
+ organization: Joi128.string().required()
46976
+ }).validate({ search, page, status, organization });
46977
+ if (error)
46978
+ return rejectValidation(error, next);
46979
+ try {
46980
+ res.json(
46981
+ await _getUsersByOrgId({
46982
+ search: value.search ?? "",
46983
+ page: value.page,
46984
+ status: value.status,
46985
+ organization: value.organization
46986
+ })
46987
+ );
46988
+ } catch (err) {
46989
+ next(err);
46990
+ }
46991
+ }
46487
46992
  async function createUserByVerification(req, res, next) {
46488
- const schema2 = Joi128.object({
46489
- id: Joi128.string().hex().length(24).required(),
46993
+ const allowedTypes = ["user-sign-up" /* USER_SIGN_UP */, "user-invite" /* USER_INVITE */];
46994
+ const validation = Joi128.object({
46995
+ id: Joi128.string().hex().required(),
46490
46996
  name: Joi128.string().required(),
46491
- type: Joi128.string().required().valid("user-sign-up" /* USER_SIGN_UP */, "user-invite" /* USER_INVITE */)
46492
- });
46493
- const { error, value } = schema2.validate({
46494
- id: req.params.id,
46495
- ...req.body
46997
+ password: Joi128.string().required(),
46998
+ type: Joi128.string().required().valid(...allowedTypes)
46496
46999
  });
47000
+ const id = req.params.id;
47001
+ const payload = { ...req.body };
47002
+ const { error, value } = validation.validate({ id, ...payload });
46497
47003
  if (error) {
46498
- const messages = error.details.map((d) => d.message).join(", ");
46499
- logger181.log({ level: "error", message: messages });
46500
- next(new BadRequestError202(messages));
47004
+ logger181.log({ level: "error", message: `${error.message}` });
47005
+ next(new BadRequestError202(error.message));
46501
47006
  return;
46502
47007
  }
46503
- const { id, name } = value;
46504
47008
  try {
46505
- await _createUserBySignUp({ id, name });
47009
+ await createUserBySignUp({ id: value.id, name: value.name });
46506
47010
  res.status(201).json({ message: "Successfully created account." });
46507
47011
  return;
46508
47012
  } catch (error2) {
@@ -46511,8 +47015,148 @@ function useUserControllerV2() {
46511
47015
  return;
46512
47016
  }
46513
47017
  }
47018
+ async function updateUserProfile(req, res, next) {
47019
+ if (!req.file) {
47020
+ next(new BadRequestError202("File is required!"));
47021
+ return;
47022
+ }
47023
+ const validation = Joi128.object({
47024
+ previousProfile: Joi128.string().hex().optional().allow("", null)
47025
+ });
47026
+ const payload = { ...req.body };
47027
+ const { error, value } = validation.validate(payload);
47028
+ if (error) {
47029
+ logger181.log({ level: "error", message: `${error.message}` });
47030
+ next(new BadRequestError202(error.message));
47031
+ return;
47032
+ }
47033
+ const user = req.headers.user ?? "";
47034
+ try {
47035
+ await _updateUserProfile({
47036
+ file: req.file,
47037
+ user,
47038
+ ...value
47039
+ });
47040
+ res.json({ message: "Successfully updated profile picture." });
47041
+ return;
47042
+ } catch (error2) {
47043
+ logger181.log({ level: "error", message: `${error2.message}` });
47044
+ next(error2);
47045
+ return;
47046
+ }
47047
+ }
47048
+ async function updateBirthday(req, res, next) {
47049
+ const MONTHS = [
47050
+ "January",
47051
+ "February",
47052
+ "March",
47053
+ "April",
47054
+ "May",
47055
+ "June",
47056
+ "July",
47057
+ "August",
47058
+ "September",
47059
+ "October",
47060
+ "November",
47061
+ "December"
47062
+ ];
47063
+ const validation = Joi128.object({
47064
+ _id: Joi128.string().hex().required(),
47065
+ month: Joi128.string().valid(...MONTHS).required(),
47066
+ day: Joi128.number().integer().min(1).max(31).required(),
47067
+ year: Joi128.number().integer().min(1900).max((/* @__PURE__ */ new Date()).getFullYear()).required()
47068
+ });
47069
+ const _id = req.params.id;
47070
+ const payload = { ...req.body };
47071
+ const { error } = validation.validate({ _id, ...payload });
47072
+ if (error) {
47073
+ logger181.log({ level: "error", message: `${error.message}` });
47074
+ next(new BadRequestError202(error.message));
47075
+ return;
47076
+ }
47077
+ try {
47078
+ const message = await _updateBirthday({ _id, ...payload });
47079
+ res.json({ message });
47080
+ return;
47081
+ } catch (error2) {
47082
+ logger181.log({ level: "error", message: `${error2.message}` });
47083
+ next(error2);
47084
+ return;
47085
+ }
47086
+ }
47087
+ async function updateUserFieldById(req, res, next) {
47088
+ const FIELDS = ["name", "email", "contact", "nric", "dateOfBirth", "profile", "gender", "defaultOrg"];
47089
+ const validation = Joi128.object({
47090
+ _id: Joi128.string().hex().required(),
47091
+ field: Joi128.string().valid(...FIELDS).required(),
47092
+ value: Joi128.when("field", {
47093
+ switch: [
47094
+ { is: "email", then: Joi128.string().email().required() },
47095
+ { is: "defaultOrg", then: Joi128.string().hex().required() }
47096
+ ],
47097
+ otherwise: Joi128.string().required()
47098
+ })
47099
+ });
47100
+ const _id = req.params.id;
47101
+ const payload = { ...req.body };
47102
+ const { error } = validation.validate({ _id, ...payload });
47103
+ if (error) {
47104
+ logger181.log({ level: "error", message: `${error.message}` });
47105
+ next(new BadRequestError202(error.message));
47106
+ return;
47107
+ }
47108
+ try {
47109
+ const message = await _updateUserFieldById({ _id, ...payload });
47110
+ res.json({ message });
47111
+ return;
47112
+ } catch (error2) {
47113
+ logger181.log({ level: "error", message: `${error2.message}` });
47114
+ next(error2);
47115
+ return;
47116
+ }
47117
+ }
47118
+ async function updatePasswordById(req, res, next) {
47119
+ const validation = Joi128.object({
47120
+ _id: Joi128.string().hex().required(),
47121
+ currentPassword: Joi128.string().required().min(8),
47122
+ newPassword: Joi128.string().required().min(8),
47123
+ passwordConfirmation: Joi128.string().required().min(8)
47124
+ });
47125
+ const _id = req.params.id;
47126
+ const payload = { ...req.body };
47127
+ const { error } = validation.validate({
47128
+ _id,
47129
+ ...payload
47130
+ });
47131
+ if (error) {
47132
+ next(new BadRequestError202(error.message));
47133
+ return;
47134
+ }
47135
+ const currentPassword = req.body.currentPassword ?? "";
47136
+ const newPassword = req.body.newPassword ?? "";
47137
+ const passwordConfirmation = req.body.passwordConfirmation ?? "";
47138
+ try {
47139
+ await _updatePasswordById(
47140
+ _id,
47141
+ currentPassword,
47142
+ newPassword,
47143
+ passwordConfirmation
47144
+ );
47145
+ res.json({ message: "Successfully updated password." });
47146
+ } catch (error2) {
47147
+ next(error2);
47148
+ }
47149
+ }
46514
47150
  return {
46515
- createUserByVerification
47151
+ getById,
47152
+ getByEmail,
47153
+ getUsersByOrgId,
47154
+ getUsers,
47155
+ createUserByVerification,
47156
+ updateUserProfile,
47157
+ updateBirthday,
47158
+ updateUserFieldById,
47159
+ updatePasswordById
46516
47160
  };
46517
47161
  }
46518
47162
  export {
@@ -46654,6 +47298,7 @@ export {
46654
47298
  occurrence_book_namespace_collection,
46655
47299
  orgSchema,
46656
47300
  overnight_parking_requests_namespace_collection,
47301
+ parseDahuaFind,
46657
47302
  pestDashboardCollection,
46658
47303
  poolDashboardCollection,
46659
47304
  promoCodeSchema,