@7365admin1/core 3.7.1 → 3.9.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
@@ -537,13 +537,13 @@ var require_logger = __commonJS({
537
537
  "use strict";
538
538
  exports.__esModule = true;
539
539
  var _utils = require_utils();
540
- var logger197 = {
540
+ var logger200 = {
541
541
  methodMap: ["debug", "info", "warn", "error"],
542
542
  level: "info",
543
543
  // Maps a given level value to the `methodMap` indexes above.
544
544
  lookupLevel: function lookupLevel(level) {
545
545
  if (typeof level === "string") {
546
- var levelMap = _utils.indexOf(logger197.methodMap, level.toLowerCase());
546
+ var levelMap = _utils.indexOf(logger200.methodMap, level.toLowerCase());
547
547
  if (levelMap >= 0) {
548
548
  level = levelMap;
549
549
  } else {
@@ -554,9 +554,9 @@ var require_logger = __commonJS({
554
554
  },
555
555
  // Can be overridden in the host environment
556
556
  log: function log(level) {
557
- level = logger197.lookupLevel(level);
558
- if (typeof console !== "undefined" && logger197.lookupLevel(logger197.level) <= level) {
559
- var method = logger197.methodMap[level];
557
+ level = logger200.lookupLevel(level);
558
+ if (typeof console !== "undefined" && logger200.lookupLevel(logger200.level) <= level) {
559
+ var method = logger200.methodMap[level];
560
560
  if (!console[method]) {
561
561
  method = "log";
562
562
  }
@@ -567,7 +567,7 @@ var require_logger = __commonJS({
567
567
  }
568
568
  }
569
569
  };
570
- exports["default"] = logger197;
570
+ exports["default"] = logger200;
571
571
  module.exports = exports["default"];
572
572
  }
573
573
  });
@@ -10822,7 +10822,8 @@ var metadataSchema3 = Joi9.object({
10822
10822
  guardPosts: Joi9.number().optional(),
10823
10823
  gracePeriod: Joi9.number().optional(),
10824
10824
  incidentCounter: Joi9.number().optional(),
10825
- incidentLogo: Joi9.string().optional().allow("", null)
10825
+ incidentLogo: Joi9.string().optional().allow("", null),
10826
+ services: Joi9.array().items(Joi9.object().unknown(true)).optional()
10826
10827
  });
10827
10828
  var updateAddressSchema = Joi9.object({
10828
10829
  line1: Joi9.string().min(3).allow("", null),
@@ -10852,7 +10853,8 @@ var allowedFieldsSite = [
10852
10853
  "metadata.guardPosts",
10853
10854
  "metadata.gracePeriod",
10854
10855
  "metadata.incidentCounter",
10855
- "metadata.incidentLogo"
10856
+ "metadata.incidentLogo",
10857
+ "metadata.services"
10856
10858
  ];
10857
10859
  var siteSchema = Joi9.object({
10858
10860
  name: Joi9.string().required(),
@@ -11746,9 +11748,7 @@ function useVerificationRepoV2() {
11746
11748
  }
11747
11749
  );
11748
11750
  } catch (error) {
11749
- throw new InternalServerError11(
11750
- "Failed to retrieve verification."
11751
- );
11751
+ throw new InternalServerError11("Failed to retrieve verification.");
11752
11752
  }
11753
11753
  }
11754
11754
  async function updateVerificationCodeById(_id, verificationCode, expireAt, session) {
@@ -11766,9 +11766,7 @@ function useVerificationRepoV2() {
11766
11766
  { session }
11767
11767
  );
11768
11768
  } catch (error) {
11769
- throw new InternalServerError11(
11770
- "Failed to update verification code."
11771
- );
11769
+ throw new InternalServerError11("Failed to update verification code.");
11772
11770
  }
11773
11771
  }
11774
11772
  return {
@@ -20787,12 +20785,20 @@ var schemaVisitorTransaction = Joi37.object({
20787
20785
  nric: Joi37.string().optional().allow(null, ""),
20788
20786
  visitorPass: Joi37.array().items(
20789
20787
  Joi37.object({
20790
- keyId: Joi37.string().hex().length(24).required()
20788
+ keyId: Joi37.string().hex().length(24).required(),
20789
+ receivedDate: Joi37.date().optional().allow(null),
20790
+ status: Joi37.string().optional().allow(null, ""),
20791
+ lastUpdate: Joi37.date().optional().allow(null),
20792
+ remarks: Joi37.string().optional().allow(null, "")
20791
20793
  })
20792
20794
  ).optional().allow(null),
20793
20795
  passKeys: Joi37.array().items(
20794
20796
  Joi37.object({
20795
- keyId: Joi37.string().hex().length(24).required()
20797
+ keyId: Joi37.string().hex().length(24).required(),
20798
+ receivedDate: Joi37.date().optional().allow(null),
20799
+ status: Joi37.string().optional().allow(null, ""),
20800
+ lastUpdate: Joi37.date().optional().allow(null),
20801
+ remarks: Joi37.string().optional().allow(null, "")
20796
20802
  })
20797
20803
  ).optional().allow(null),
20798
20804
  contact: Joi37.string().optional().allow(null, "")
@@ -20809,19 +20815,28 @@ var schemaVisitorTransaction = Joi37.object({
20809
20815
  numberOfPassengers: Joi37.number().integer().optional().allow(null, ""),
20810
20816
  visitorPass: Joi37.array().items(
20811
20817
  Joi37.object({
20812
- keyId: Joi37.string().hex().length(24).allow(null, "")
20818
+ keyId: Joi37.string().hex().length(24).allow(null, ""),
20819
+ receivedDate: Joi37.date().optional().allow(null),
20820
+ status: Joi37.string().optional().allow(null, ""),
20821
+ lastUpdate: Joi37.date().optional().allow(null),
20822
+ remarks: Joi37.string().optional().allow(null, "")
20813
20823
  })
20814
20824
  ).optional().allow(null),
20815
20825
  passKeys: Joi37.array().items(
20816
20826
  Joi37.object({
20817
- keyId: Joi37.string().hex().length(24).allow(null, "")
20827
+ keyId: Joi37.string().hex().length(24).allow(null, ""),
20828
+ receivedDate: Joi37.date().optional().allow(null),
20829
+ status: Joi37.string().optional().allow(null, ""),
20830
+ lastUpdate: Joi37.date().optional().allow(null),
20831
+ remarks: Joi37.string().optional().allow(null, "")
20818
20832
  })
20819
20833
  ).optional().allow(null),
20820
20834
  checkInRemarks: Joi37.string().optional().allow("", null),
20821
20835
  checkOutRemarks: Joi37.string().optional().allow("", null),
20822
20836
  expectedCheckIn: Joi37.string().isoDate().optional(),
20823
20837
  purpose: Joi37.string().optional().allow(null, ""),
20824
- inviterId: Joi37.any().optional().allow(null, "")
20838
+ inviterId: Joi37.any().optional().allow(null, ""),
20839
+ createdBy: Joi37.string().hex().length(24).optional().allow(null, "")
20825
20840
  });
20826
20841
  var schemaUpdateVisTrans = Joi37.object({
20827
20842
  _id: Joi37.string().hex().length(24).required(),
@@ -20941,22 +20956,22 @@ function MVisitorTransaction(value) {
20941
20956
  throw new Error("Invalid type for manualCheckout key.");
20942
20957
  }
20943
20958
  }
20944
- if (value.visitorPass && Array.isArray(value.visitorPass) && value.visitorPass.length > 0) {
20959
+ if (Array.isArray(value.visitorPass)) {
20945
20960
  value.visitorPass = value.visitorPass.map((v) => {
20946
- if (typeof v === "string")
20947
- return { keyId: new ObjectId39(v) };
20948
- if (v?.keyId && typeof v.keyId === "string") {
20949
- return { keyId: new ObjectId39(v.keyId) };
20961
+ try {
20962
+ v.keyId = new ObjectId39(v.keyId);
20963
+ } catch (error2) {
20964
+ throw new Error("Invalid VisitorPass ID.");
20950
20965
  }
20951
20966
  return v;
20952
20967
  });
20953
20968
  }
20954
- if (value.passKeys && Array.isArray(value.passKeys) && value.passKeys.length > 0) {
20969
+ if (Array.isArray(value.passKeys)) {
20955
20970
  value.passKeys = value.passKeys.map((p) => {
20956
- if (typeof p === "string")
20957
- return { keyId: new ObjectId39(p) };
20958
- if (p?.keyId && typeof p.keyId === "string") {
20959
- return { keyId: new ObjectId39(p.keyId) };
20971
+ try {
20972
+ p.keyId = new ObjectId39(p.keyId);
20973
+ } catch (error2) {
20974
+ throw new Error("Invalid PassKey ID.");
20960
20975
  }
20961
20976
  return p;
20962
20977
  });
@@ -21651,9 +21666,57 @@ function useVisitorTransactionRepo() {
21651
21666
  }
21652
21667
  }
21653
21668
  async function resendEmailInvitedResident(visitorId, updatedBy) {
21654
- const updatedDocument = await collection.findOne({
21655
- _id: await convertObjectIdUtil(visitorId)
21656
- });
21669
+ const pipeline = [
21670
+ { $match: { _id: await convertObjectIdUtil(visitorId) } },
21671
+ {
21672
+ $lookup: {
21673
+ from: "buildings",
21674
+ localField: "block",
21675
+ foreignField: "_id",
21676
+ as: "blockDetails"
21677
+ }
21678
+ },
21679
+ {
21680
+ $addFields: {
21681
+ blockName: {
21682
+ $ifNull: [
21683
+ { $arrayElemAt: ["$blockDetails.name", 0] },
21684
+ "Unknown"
21685
+ ]
21686
+ }
21687
+ }
21688
+ },
21689
+ {
21690
+ $project: {
21691
+ blockDetails: 0
21692
+ }
21693
+ },
21694
+ {
21695
+ $lookup: {
21696
+ from: "building-levels",
21697
+ localField: "level",
21698
+ foreignField: "_id",
21699
+ as: "levelDetails"
21700
+ }
21701
+ },
21702
+ {
21703
+ $addFields: {
21704
+ levelName: {
21705
+ $ifNull: [
21706
+ { $arrayElemAt: ["$levelDetails.name", 0] },
21707
+ "Unknown"
21708
+ ]
21709
+ }
21710
+ }
21711
+ },
21712
+ {
21713
+ $project: {
21714
+ levelDetails: 0
21715
+ }
21716
+ }
21717
+ ];
21718
+ const results = await collection.aggregate(pipeline).toArray();
21719
+ const updatedDocument = results[0] || null;
21657
21720
  if (!updatedDocument?.email)
21658
21721
  return;
21659
21722
  if (!updatedDocument?._id)
@@ -21668,7 +21731,7 @@ function useVisitorTransactionRepo() {
21668
21731
  name: `${updatedDocument?.name}`,
21669
21732
  plateNumber: updatedDocument?.plateNumber,
21670
21733
  nric: updatedDocument?.nric,
21671
- address: `${updatedDocument?.block} ${updatedDocument?.level} ${updatedDocument?.unitName}`,
21734
+ address: `${updatedDocument?.blockName} ${updatedDocument?.levelName} ${updatedDocument?.unitName}`,
21672
21735
  contactNumber: updatedDocument?.contact ? updatedDocument?.contact : "N/A",
21673
21736
  email: updatedDocument?.email ? updatedDocument?.email : "N/A",
21674
21737
  duration: updatedDocument?.duration ? updatedDocument?.duration : "N/A",
@@ -27615,7 +27678,7 @@ function useBuildingRepo() {
27615
27678
  try {
27616
27679
  await collection.createIndexes([
27617
27680
  { key: { name: "text" }, name: "text-index" },
27618
- { key: { name: 1 }, unique: true, name: "unique-name-index" },
27681
+ // { key: { name: 1 }, unique: true, name: "unique-name-index" },
27619
27682
  { key: { site: 1 } },
27620
27683
  { key: { createdAt: 1 } },
27621
27684
  {
@@ -28307,11 +28370,6 @@ function useBuildingLevelRepo() {
28307
28370
  try {
28308
28371
  await collection.createIndexes([
28309
28372
  // Ensure name is unique per blockId
28310
- {
28311
- key: { blockId: 1, name: 1 },
28312
- unique: true,
28313
- name: "unique_name_per_blockId"
28314
- },
28315
28373
  // Other useful indexes
28316
28374
  { key: { site: 1 }, name: "idx_site" },
28317
28375
  { key: { blockId: 1 }, name: "idx_blockId" },
@@ -28572,7 +28630,11 @@ function useBuildingLevelRepo() {
28572
28630
  const res = await collection.bulkWrite(operations, { session });
28573
28631
  delCachedData();
28574
28632
  return {
28575
- insertedIds: res.insertedIds
28633
+ insertedIds: res.insertedIds,
28634
+ levels: levels.map((l, i) => ({
28635
+ _id: res.insertedIds[i],
28636
+ name: l.name
28637
+ }))
28576
28638
  };
28577
28639
  } catch (error) {
28578
28640
  logger63.log({
@@ -28856,8 +28918,8 @@ function useBuildingService() {
28856
28918
  const name = row.name;
28857
28919
  const rawLevel = row.level?.toString().trim();
28858
28920
  const rawUnit = row.unit?.toString().trim();
28859
- const normalizedLevel = /^(na|n\/a)$/i.test(rawLevel) ? null : `Lvl${rawLevel}`;
28860
- const normalizedUnit = /^(na|n\/a)$/i.test(rawUnit) ? null : `Unit ${rawUnit}`;
28921
+ const normalizedLevel = /^(na|n\/a)$/i.test(rawLevel) ? null : rawLevel;
28922
+ const normalizedUnit = /^(na|n\/a)$/i.test(rawUnit) ? null : rawUnit;
28861
28923
  if (!blockMap.has(block)) {
28862
28924
  blockMap.set(block, { name, levels: [], unitsByLevel: /* @__PURE__ */ new Map() });
28863
28925
  }
@@ -28878,57 +28940,76 @@ function useBuildingService() {
28878
28940
  }
28879
28941
  }
28880
28942
  }
28881
- const buildingPayloads = Array.from(blockMap.entries()).map(
28882
- ([block, { name, levels }]) => ({
28943
+ const buildingPayloads = [];
28944
+ const buildingUnitPayloads = [];
28945
+ for (const [
28946
+ block,
28947
+ { name, levels, unitsByLevel }
28948
+ ] of blockMap.entries()) {
28949
+ const buildingId = new ObjectId53();
28950
+ const levelsPayload = (levels ?? []).map((levelName) => ({
28951
+ blockId: buildingId.toString(),
28952
+ site: site.toString(),
28953
+ name: levelName,
28954
+ status: "active" /* ACTIVE */,
28955
+ createdAt: /* @__PURE__ */ new Date(),
28956
+ updatedAt: null,
28957
+ deletedAt: null
28958
+ }));
28959
+ let insertedLevels;
28960
+ if (levelsPayload.length > 0) {
28961
+ insertedLevels = await _bulkWriteLevels(levelsPayload, session);
28962
+ }
28963
+ const levelNameToId = /* @__PURE__ */ new Map();
28964
+ if (insertedLevels) {
28965
+ insertedLevels.levels.forEach((lvl) => {
28966
+ levelNameToId.set(lvl.name, lvl._id);
28967
+ });
28968
+ }
28969
+ const buildingPayload = {
28970
+ _id: buildingId,
28883
28971
  site,
28884
28972
  block,
28885
28973
  name,
28886
- levels
28887
- })
28888
- );
28889
- const blockToBuildingId = /* @__PURE__ */ new Map();
28890
- for (const buildingPayload of buildingPayloads) {
28891
- const result = await _add(buildingPayload);
28892
- blockToBuildingId.set(buildingPayload.block, result);
28893
- }
28894
- const buildingUnitPayloads = [];
28895
- Array.from(blockMap.entries()).forEach(
28896
- ([block, { name, unitsByLevel }]) => {
28897
- const buildingId = blockToBuildingId.get(block);
28898
- Array.from(unitsByLevel.entries()).forEach(([level, units]) => {
28899
- units.forEach((unit) => {
28900
- buildingUnitPayloads.push({
28901
- site,
28902
- name: unit,
28903
- building: buildingId.toString(),
28904
- buildingName: name,
28905
- block,
28906
- level,
28907
- category: "",
28908
- status: "active" /* ACTIVE */,
28909
- buildingUnitFiles: [],
28910
- owner: "",
28911
- ownerName: "",
28912
- companyName: "",
28913
- companyRegistrationNumber: "",
28914
- billing: [],
28915
- unitNumber: parseInt(unit.replace("Unit ", ""), 10) || null,
28916
- createdAt: /* @__PURE__ */ new Date(),
28917
- updatedAt: "",
28918
- deletedAt: ""
28919
- });
28974
+ levels: insertedLevels ? Object.values(insertedLevels.insertedIds) : []
28975
+ };
28976
+ const buildingResult = await _add(buildingPayload, session);
28977
+ Array.from(unitsByLevel.entries()).forEach(([levelName, units]) => {
28978
+ const levelId = levelNameToId.get(levelName);
28979
+ units.forEach((unit) => {
28980
+ buildingUnitPayloads.push({
28981
+ site: new ObjectId53(site),
28982
+ name: unit,
28983
+ building: buildingId,
28984
+ // already an ObjectId
28985
+ buildingName: name,
28986
+ block,
28987
+ level: levelId,
28988
+ // ✅ use ObjectId instead of string
28989
+ category: "",
28990
+ status: "active" /* ACTIVE */,
28991
+ buildingUnitFiles: [],
28992
+ owner: "",
28993
+ ownerName: "",
28994
+ companyName: "",
28995
+ companyRegistrationNumber: "",
28996
+ billing: [],
28997
+ unitNumber: parseInt(unit.replace("Unit ", ""), 10) || null,
28998
+ createdAt: /* @__PURE__ */ new Date(),
28999
+ updatedAt: "",
29000
+ deletedAt: ""
28920
29001
  });
28921
29002
  });
28922
- }
28923
- );
29003
+ });
29004
+ }
28924
29005
  await _bulkAddBuildingUnits(buildingUnitPayloads);
28925
- await session?.commitTransaction();
29006
+ await session.commitTransaction();
28926
29007
  return { buildingPayloads, buildingUnitPayloads };
28927
29008
  } catch (error) {
28928
- await session?.abortTransaction();
29009
+ await session.abortTransaction();
28929
29010
  throw error;
28930
29011
  } finally {
28931
- session?.endSession();
29012
+ session.endSession();
28932
29013
  }
28933
29014
  }
28934
29015
  return {
@@ -29199,9 +29280,9 @@ function useBuildingController() {
29199
29280
  const lowerName = originalname.toLowerCase();
29200
29281
  const rowSchema = Joi46.object({
29201
29282
  block: Joi46.number().integer().min(0).required(),
29202
- level: Joi46.string().optional().allow(null, ""),
29203
- unit: Joi46.string().optional().allow(null, ""),
29204
- category: Joi46.string().trim().required(),
29283
+ level: Joi46.alternatives().try(Joi46.string(), Joi46.number()).custom((value) => String(value)).optional().allow(null, ""),
29284
+ unit: Joi46.alternatives().try(Joi46.string(), Joi46.number()).custom((value) => String(value)).optional().allow(null, ""),
29285
+ category: Joi46.string().trim().optional().allow(null, ""),
29205
29286
  name: Joi46.string().trim().optional().allow(null, ""),
29206
29287
  email: Joi46.string().email().lowercase().optional().allow(null, ""),
29207
29288
  phoneNumber: Joi46.string().trim().optional().allow(null, "")
@@ -29215,11 +29296,9 @@ function useBuildingController() {
29215
29296
  { abortEarly: false, convert: true }
29216
29297
  );
29217
29298
  if (queryError) {
29218
- next(
29219
- new BadRequestError84(
29220
- queryError.details.map((d) => d.message).join(", ")
29221
- )
29222
- );
29299
+ const messages = queryError.details.map((d) => d.message).join(", ");
29300
+ logger65.log({ level: "error", message: messages });
29301
+ next(new BadRequestError84(messages));
29223
29302
  return;
29224
29303
  }
29225
29304
  const { site, org } = queryValue;
@@ -29254,11 +29333,11 @@ function useBuildingController() {
29254
29333
  } else if (lowerName.endsWith(".csv")) {
29255
29334
  rows = await new Promise((resolve, reject) => {
29256
29335
  const parsed = [];
29257
- fs2.createReadStream(path5).pipe(csv()).on("headers", (headers) => {
29258
- headers = headers.map(
29259
- (h) => h.trim().replace(/\(.*\)/, "").trim()
29260
- );
29261
- }).on("data", (row) => parsed.push(row)).on("end", () => resolve(parsed)).on("error", reject);
29336
+ fs2.createReadStream(path5).pipe(
29337
+ csv({
29338
+ mapHeaders: ({ header }) => header.trim().replace(/\(.*\)/, "").trim()
29339
+ })
29340
+ ).on("data", (row) => parsed.push(row)).on("end", () => resolve(parsed)).on("error", reject);
29262
29341
  });
29263
29342
  } else {
29264
29343
  next(
@@ -29276,6 +29355,7 @@ function useBuildingController() {
29276
29355
  if (error) {
29277
29356
  invalidRows.push({
29278
29357
  row: index + 2,
29358
+ // +2 because header is row 1
29279
29359
  data: row,
29280
29360
  errors: error.details.map((d) => d.message)
29281
29361
  });
@@ -29297,6 +29377,7 @@ function useBuildingController() {
29297
29377
  fs2.unlink(path5, () => {
29298
29378
  });
29299
29379
  } catch (error) {
29380
+ console.log(error);
29300
29381
  logger65.log({ level: "error", message: error.message });
29301
29382
  next(error);
29302
29383
  }
@@ -33271,17 +33352,13 @@ var KeyRepo = class {
33271
33352
  }
33272
33353
  }
33273
33354
  static async updateKeyById(keyId, key, site, session, isChild) {
33274
- try {
33275
- keyId = new ObjectId61(keyId);
33276
- if (site)
33277
- site = new ObjectId61(site);
33278
- if (key.updatedBy)
33279
- key.updatedBy = await convertObjectIdUtil(key.updatedBy);
33280
- if (!key.status)
33281
- delete key.status;
33282
- } catch (error) {
33283
- return Promise.reject("Invalid key id");
33284
- }
33355
+ keyId = await convertObjectIdUtil2(keyId, "keyId");
33356
+ if (site)
33357
+ site = await convertObjectIdUtil2(site, "Site");
33358
+ if (key.updatedBy)
33359
+ key.updatedBy = await convertObjectIdUtil2(key.updatedBy, "Updated By");
33360
+ if (!key.status)
33361
+ delete key.status;
33285
33362
  try {
33286
33363
  key.updatedAt = /* @__PURE__ */ new Date();
33287
33364
  const query = { _id: keyId, ...site && { site } };
@@ -33294,6 +33371,7 @@ var KeyRepo = class {
33294
33371
  { session }
33295
33372
  );
33296
33373
  let setKeys = [];
33374
+ console.log("updateKeyById result", result);
33297
33375
  if (result.modifiedCount > 0) {
33298
33376
  const updatedDocs = await this.collection().find(find).toArray();
33299
33377
  if (Array.isArray(updatedDocs) && updatedDocs.length > 0) {
@@ -33308,10 +33386,12 @@ var KeyRepo = class {
33308
33386
  await this.collectionDynamic("keys-histories").insertMany(setKeys, {
33309
33387
  session
33310
33388
  });
33389
+ } else {
33390
+ throw new Error("Failed Updating Keys");
33311
33391
  }
33312
33392
  return result;
33313
33393
  } catch (error) {
33314
- console.log(error);
33394
+ throw new Error(error);
33315
33395
  }
33316
33396
  }
33317
33397
  static async deleteKeyById(_id, session) {
@@ -33394,6 +33474,176 @@ var KeyRepo = class {
33394
33474
  }
33395
33475
  };
33396
33476
 
33477
+ // src/services/notification.service.ts
33478
+ import { sendExpoPushNotifications } from "iservice365-expo-notifications";
33479
+
33480
+ // src/repositories/push-token.repository.ts
33481
+ var PushTokenRepo = class {
33482
+ static collection() {
33483
+ return getDB().collection("push_tokens");
33484
+ }
33485
+ static async createIndexes() {
33486
+ await Promise.all([
33487
+ this.collection().createIndex({ token: 1 }, { unique: true }),
33488
+ this.collection().createIndex({ userId: 1, platform: 1 }),
33489
+ this.collection().createIndex({ siteId: 1 })
33490
+ ]);
33491
+ }
33492
+ static async upsert(userId, token, platform, siteId, projectId, appSlug) {
33493
+ const now = /* @__PURE__ */ new Date();
33494
+ const p = platform;
33495
+ const existing = await this.collection().findOne({ token });
33496
+ if (existing) {
33497
+ await this.collection().updateOne(
33498
+ { token },
33499
+ {
33500
+ $set: {
33501
+ userId,
33502
+ platform: p,
33503
+ siteId,
33504
+ projectId,
33505
+ appSlug,
33506
+ updatedAt: now
33507
+ }
33508
+ }
33509
+ );
33510
+ return;
33511
+ }
33512
+ await this.collection().deleteMany({ userId, platform: p });
33513
+ await this.collection().insertOne({
33514
+ userId,
33515
+ siteId,
33516
+ token,
33517
+ platform: p,
33518
+ projectId,
33519
+ appSlug,
33520
+ createdAt: now,
33521
+ updatedAt: now
33522
+ });
33523
+ }
33524
+ static async remove(token) {
33525
+ await this.collection().deleteMany({ token });
33526
+ }
33527
+ static async findTokensByUserIds(userIds, appSlug) {
33528
+ const docs = await this.collection().find({ userId: { $in: userIds }, appSlug: { $eq: appSlug } }).toArray();
33529
+ return docs.map((d) => d.token);
33530
+ }
33531
+ };
33532
+
33533
+ // src/services/notification.service.ts
33534
+ function toStringArray(recipient) {
33535
+ const arr = Array.isArray(recipient) ? recipient : [recipient];
33536
+ return arr.map((r) => r.toString());
33537
+ }
33538
+ async function send(userIds, title, body, data, isForMAMobileApp = false, appSlug) {
33539
+ try {
33540
+ let tokens = [];
33541
+ if (isForMAMobileApp) {
33542
+ tokens = await PushTokenRepo.findTokensByUserIds(userIds, appSlug);
33543
+ } else {
33544
+ tokens = await PushTokenRepo.findTokensByUserIds(userIds);
33545
+ }
33546
+ if (!tokens.length)
33547
+ return;
33548
+ for (const token of tokens) {
33549
+ await sendExpoPushNotifications([token], { title, body, data });
33550
+ }
33551
+ } catch (error) {
33552
+ console.warn("[NotificationService]", error);
33553
+ }
33554
+ }
33555
+ var NotificationService = class {
33556
+ static async bulletinBoardCreated(payload) {
33557
+ await send(
33558
+ toStringArray(payload.to),
33559
+ "Bulletin Board",
33560
+ `There is new ${payload.status} bulletin board.`,
33561
+ {
33562
+ bulletinId: payload.bulletinId.toString(),
33563
+ status: payload.status,
33564
+ module: "feedback",
33565
+ screen: "/(user)/bulletinInfo",
33566
+ params: {
33567
+ id: payload.bulletinId.toString()
33568
+ }
33569
+ },
33570
+ false,
33571
+ "iservice365-resident-mobile-app"
33572
+ );
33573
+ }
33574
+ static async prelovedMarketplacePostCreation(payload) {
33575
+ await send(
33576
+ toStringArray(payload.to),
33577
+ "Preloved Marketplace",
33578
+ `New preloved marketplace post added.`,
33579
+ {
33580
+ prelovedId: payload.prelovedId.toString(),
33581
+ status: payload.status,
33582
+ module: "prelovedMarketplace",
33583
+ screen: "/(user)/(marketplace)/prelovedPostInfo",
33584
+ params: {
33585
+ id: payload.prelovedId.toString()
33586
+ }
33587
+ },
33588
+ false,
33589
+ "iservice365-resident-mobile-app"
33590
+ );
33591
+ }
33592
+ static async bulletinBoardCreatedForMA(payload) {
33593
+ await send(
33594
+ toStringArray(payload.to),
33595
+ "Bulletin Board",
33596
+ `There is new ${payload.status} bulletin board.`,
33597
+ {
33598
+ bulletinId: payload.bulletinId.toString(),
33599
+ status: payload.status,
33600
+ module: "feedback",
33601
+ screen: "/(user)/(bulletin-board)",
33602
+ params: {
33603
+ id: payload.bulletinId.toString()
33604
+ }
33605
+ },
33606
+ true,
33607
+ "iservice365-ma-mobile-app"
33608
+ );
33609
+ }
33610
+ static async eventCreatedForMA(payload) {
33611
+ await send(
33612
+ toStringArray(payload.to),
33613
+ "Event",
33614
+ `There is new ${payload.status} event.`,
33615
+ {
33616
+ eventId: payload.eventId.toString(),
33617
+ status: payload.status,
33618
+ module: "event",
33619
+ screen: "/(user)/(events)",
33620
+ params: {
33621
+ id: payload.eventId.toString()
33622
+ }
33623
+ },
33624
+ true,
33625
+ "iservice365-ma-mobile-app"
33626
+ );
33627
+ }
33628
+ static async invitedVisitorCheckOutForMa(payload) {
33629
+ await send(
33630
+ toStringArray(payload.to),
33631
+ "Invited Visitor Check Out",
33632
+ `The invited visitor ${payload.name}, has been checked out.`,
33633
+ {
33634
+ visitorTransactionId: payload._id.toString(),
33635
+ module: "visitors",
33636
+ screen: "/(user)/visitor-management",
33637
+ params: {
33638
+ id: payload._id.toString()
33639
+ }
33640
+ },
33641
+ true,
33642
+ "iservice365-ma-mobile-app"
33643
+ );
33644
+ }
33645
+ };
33646
+
33397
33647
  // src/services/visitor-transaction.service.ts
33398
33648
  function useVisitorTransactionService() {
33399
33649
  const MailerConfig = {
@@ -33432,6 +33682,7 @@ function useVisitorTransactionService() {
33432
33682
  getBlocklistedVehicleByPlateNumber: _getBlocklistedVehicleByPlateNumber
33433
33683
  } = useVehicleRepo();
33434
33684
  const { getById: _getUnitById } = useBuildingUnitRepo();
33685
+ const { getUsersBySiteId } = useMemberRepo();
33435
33686
  function extractKeyId(item) {
33436
33687
  if (!item)
33437
33688
  return null;
@@ -33581,47 +33832,50 @@ function useVisitorTransactionService() {
33581
33832
  const chunk = value.members.slice(i, i + chunkSize);
33582
33833
  for (const member of chunk) {
33583
33834
  await KeyRepo.checkPassKeyAvailability(member.visitorPass, member.passKeys);
33584
- if (member.visitorPass && Array.isArray(member.visitorPass) && member.visitorPass.length > 0) {
33585
- for (const vp of member.visitorPass) {
33586
- try {
33587
- const updatePayload = { status: "In Use" /* IN_USE */ };
33588
- const visitorPassId = typeof vp === "string" || vp instanceof ObjectId62 ? vp : vp.keyId;
33589
- if (!visitorPassId)
33590
- value.visitorPass = [];
33591
- await KeyRepo.updateKeyById(
33592
- visitorPassId,
33593
- updatePayload,
33594
- value.site
33595
- );
33596
- } catch (error) {
33597
- throw error;
33598
- }
33835
+ if (Array.isArray(member.visitorPass)) {
33836
+ for (const item of member.visitorPass) {
33837
+ console.log("Type of keyId:", typeof item.keyId);
33838
+ console.log("item visitorPass", item);
33839
+ await KeyRepo.updateKeyById(
33840
+ item.keyId,
33841
+ {
33842
+ status: "In Use" /* IN_USE */,
33843
+ updatedBy: value.createdBy
33844
+ },
33845
+ value.site,
33846
+ session
33847
+ );
33848
+ item.receivedDate = /* @__PURE__ */ new Date();
33849
+ item.status = "Not Returned" /* NOT_RETURNED */;
33850
+ item.lastUpdate = null;
33851
+ item.remarks = "";
33599
33852
  }
33600
33853
  }
33601
- if (member.passKeys && Array.isArray(member.passKeys) && member.passKeys.length > 0) {
33602
- for (const pk of member.passKeys) {
33603
- try {
33604
- const updatePayload = { status: "In Use" /* IN_USE */ };
33605
- const passKeyId = typeof pk === "string" || pk instanceof ObjectId62 ? pk : pk.keyId;
33606
- if (!passKeyId)
33607
- value.passKeys = [];
33608
- await KeyRepo.updateKeyById(
33609
- passKeyId,
33610
- updatePayload,
33611
- value.site
33612
- );
33613
- } catch (error) {
33614
- throw error;
33615
- }
33854
+ if (Array.isArray(member.passKeys)) {
33855
+ for (const item of member.passKeys) {
33856
+ await KeyRepo.updateKeyById(
33857
+ item.keyId,
33858
+ {
33859
+ status: "In Use" /* IN_USE */,
33860
+ updatedBy: value.createdBy
33861
+ },
33862
+ value.site,
33863
+ session
33864
+ );
33865
+ item.receivedDate = /* @__PURE__ */ new Date();
33866
+ item.status = "Not Returned" /* NOT_RETURNED */;
33867
+ item.lastUpdate = null;
33868
+ item.remarks = "";
33616
33869
  }
33617
33870
  }
33618
33871
  }
33619
33872
  await Promise.all(
33620
33873
  chunk.map((member) => {
33621
- const { visitorPass, passKeys } = member;
33874
+ const clonedMember = structuredClone(member);
33875
+ const { visitorPass, passKeys } = clonedMember;
33622
33876
  return _add(
33623
33877
  {
33624
- ...member,
33878
+ ...clonedMember,
33625
33879
  block,
33626
33880
  level,
33627
33881
  unit,
@@ -33668,38 +33922,38 @@ function useVisitorTransactionService() {
33668
33922
  throw new BadRequestError100("This plate number is blocklisted");
33669
33923
  }
33670
33924
  await KeyRepo.checkPassKeyAvailability(value.visitorPass, value.passKeys);
33671
- if (value.visitorPass && Array.isArray(value.visitorPass) && value.visitorPass.length > 0 && value.visitorPass) {
33672
- for (const vp of value.visitorPass) {
33673
- try {
33674
- const updatePayload = { status: "In Use" /* IN_USE */ };
33675
- const visitorPassId = typeof vp === "string" || vp instanceof ObjectId62 ? vp : vp.keyId;
33676
- if (!visitorPassId)
33677
- value.visitorPass = [];
33678
- await KeyRepo.updateKeyById(
33679
- visitorPassId,
33680
- updatePayload,
33681
- value.site
33682
- );
33683
- } catch (error) {
33684
- throw error;
33685
- }
33925
+ if (Array.isArray(value.visitorPass)) {
33926
+ for (const item of value.visitorPass) {
33927
+ await KeyRepo.updateKeyById(
33928
+ item.keyId,
33929
+ {
33930
+ status: "In Use" /* IN_USE */,
33931
+ updatedBy: value.createdBy
33932
+ },
33933
+ value.site,
33934
+ session
33935
+ );
33936
+ item.receivedDate = /* @__PURE__ */ new Date();
33937
+ item.status = "Not Returned" /* NOT_RETURNED */;
33938
+ item.lastUpdate = null;
33939
+ item.remarks = "";
33686
33940
  }
33687
33941
  }
33688
- if (value.passKeys && Array.isArray(value.passKeys) && value.passKeys.length > 0) {
33689
- for (const pk of value.passKeys) {
33690
- try {
33691
- const updatePayload = { status: "In Use" /* IN_USE */ };
33692
- const passKeyId = typeof pk === "string" || pk instanceof ObjectId62 ? pk : pk.keyId;
33693
- if (!passKeyId)
33694
- value.passKeys = [];
33695
- await KeyRepo.updateKeyById(
33696
- passKeyId,
33697
- updatePayload,
33698
- value.site
33699
- );
33700
- } catch (error) {
33701
- throw error;
33702
- }
33942
+ if (Array.isArray(value.passKeys)) {
33943
+ for (const item of value.passKeys) {
33944
+ await KeyRepo.updateKeyById(
33945
+ item.keyId,
33946
+ {
33947
+ status: "In Use" /* IN_USE */,
33948
+ updatedBy: value.createdBy
33949
+ },
33950
+ value.site,
33951
+ session
33952
+ );
33953
+ item.receivedDate = /* @__PURE__ */ new Date();
33954
+ item.status = "Not Returned" /* NOT_RETURNED */;
33955
+ item.lastUpdate = null;
33956
+ item.remarks = "";
33703
33957
  }
33704
33958
  }
33705
33959
  const result = await _add(value, session);
@@ -33869,6 +34123,28 @@ function useVisitorTransactionService() {
33869
34123
  }
33870
34124
  }
33871
34125
  console.log("Open barrier response:", openBarrier);
34126
+ const visitorTransaction = await _getVisitorTransactionById(
34127
+ id.toString()
34128
+ );
34129
+ if (!visitorTransaction) {
34130
+ throw new Error("Visitor transaction not found.");
34131
+ }
34132
+ if (value.checkOut && visitorTransaction.type === "guest" /* GUEST */) {
34133
+ const users = await getUsersBySiteId({
34134
+ status: "active",
34135
+ siteId: visitorTransaction.site.toString()
34136
+ });
34137
+ if (users?.length > 0) {
34138
+ const userIds = Array.from(
34139
+ new Set(users.map((item) => item.user.toString()))
34140
+ );
34141
+ NotificationService.invitedVisitorCheckOutForMa({
34142
+ to: userIds,
34143
+ name: visitorTransaction.name,
34144
+ _id: id.toString()
34145
+ });
34146
+ }
34147
+ }
33872
34148
  await session?.commitTransaction();
33873
34149
  return "Successfully updated visitor transaction.";
33874
34150
  } catch (error) {
@@ -33960,9 +34236,9 @@ function useVisitorTransactionService() {
33960
34236
  value.checkIn = null;
33961
34237
  const payload = {
33962
34238
  ...value,
33963
- block: inviter?.block,
33964
- level: inviter?.level,
33965
- unit: inviter?.unit,
34239
+ block: inviter?.block?.toString(),
34240
+ level: inviter?.level?.toString(),
34241
+ unit: inviter?.unit?.toString(),
33966
34242
  unitName: unit?.name,
33967
34243
  org: inviter?.org.toString(),
33968
34244
  site: inviter?.site.toString(),
@@ -34058,7 +34334,8 @@ function useVisitorTransactionController() {
34058
34334
  } = useVisitorTransactionRepo();
34059
34335
  async function add(req, res, next) {
34060
34336
  try {
34061
- const { error, value } = schemaVisitorTransaction.validate(req.body, {
34337
+ const { companyName, firstName, lastName, ...restData } = req.body;
34338
+ const { error, value } = schemaVisitorTransaction.validate(restData, {
34062
34339
  abortEarly: false
34063
34340
  });
34064
34341
  if (error) {
@@ -34290,8 +34567,11 @@ function useVisitorTransactionController() {
34290
34567
  return;
34291
34568
  } catch (error2) {
34292
34569
  logger81.log({ level: "error", message: error2.message });
34293
- next(error2);
34294
- return;
34570
+ if (error2?.message) {
34571
+ next(new BadRequestError101(error2?.message));
34572
+ } else {
34573
+ next(error2);
34574
+ }
34295
34575
  }
34296
34576
  }
34297
34577
  async function changeVisitorTransactionKeysById(req, res, next) {
@@ -41032,120 +41312,6 @@ function useBulletinBoardRepo() {
41032
41312
  // src/services/bulletin-board.service.ts
41033
41313
  import { useAtlas as useAtlas68, NotFoundError as NotFoundError30 } from "@7365admin1/node-server-utils";
41034
41314
  import { ObjectId as ObjectId85 } from "mongodb";
41035
-
41036
- // src/services/notification.service.ts
41037
- import { sendExpoPushNotifications } from "iservice365-expo-notifications";
41038
-
41039
- // src/repositories/push-token.repository.ts
41040
- var PushTokenRepo = class {
41041
- static collection() {
41042
- return getDB().collection("push_tokens");
41043
- }
41044
- static async createIndexes() {
41045
- await Promise.all([
41046
- this.collection().createIndex({ token: 1 }, { unique: true }),
41047
- this.collection().createIndex({ userId: 1, platform: 1 }),
41048
- this.collection().createIndex({ siteId: 1 })
41049
- ]);
41050
- }
41051
- static async upsert(userId, token, platform, siteId, projectId, appSlug) {
41052
- const now = /* @__PURE__ */ new Date();
41053
- const p = platform;
41054
- const existing = await this.collection().findOne({ token });
41055
- if (existing) {
41056
- await this.collection().updateOne(
41057
- { token },
41058
- {
41059
- $set: {
41060
- userId,
41061
- platform: p,
41062
- siteId,
41063
- projectId,
41064
- appSlug,
41065
- updatedAt: now
41066
- }
41067
- }
41068
- );
41069
- return;
41070
- }
41071
- await this.collection().deleteMany({ userId, platform: p });
41072
- await this.collection().insertOne({
41073
- userId,
41074
- siteId,
41075
- token,
41076
- platform: p,
41077
- projectId,
41078
- appSlug,
41079
- createdAt: now,
41080
- updatedAt: now
41081
- });
41082
- }
41083
- static async remove(token) {
41084
- await this.collection().deleteMany({ token });
41085
- }
41086
- static async findTokensByUserIds(userIds, appSlug) {
41087
- const docs = await this.collection().find({ userId: { $in: userIds }, appSlug: { $eq: appSlug } }).toArray();
41088
- return docs.map((d) => d.token);
41089
- }
41090
- };
41091
-
41092
- // src/services/notification.service.ts
41093
- function toStringArray(recipient) {
41094
- const arr = Array.isArray(recipient) ? recipient : [recipient];
41095
- return arr.map((r) => r.toString());
41096
- }
41097
- async function send(userIds, title, body, data, appSlug) {
41098
- try {
41099
- const tokens = Array.from(
41100
- new Set(await PushTokenRepo.findTokensByUserIds(userIds, appSlug))
41101
- );
41102
- if (!tokens.length)
41103
- return;
41104
- for (const token of tokens) {
41105
- await sendExpoPushNotifications([token], { title, body, data });
41106
- }
41107
- } catch (error) {
41108
- console.warn("[NotificationService]", error);
41109
- }
41110
- }
41111
- var NotificationService = class {
41112
- static async bulletinBoardCreated(payload) {
41113
- await send(
41114
- toStringArray(payload.to),
41115
- "Bulletin Board",
41116
- `There is new ${payload.status} bulletin board.`,
41117
- {
41118
- bulletinId: payload.bulletinId.toString(),
41119
- status: payload.status,
41120
- module: "feedback",
41121
- screen: "/(user)/bulletinInfo",
41122
- params: {
41123
- id: payload.bulletinId.toString()
41124
- }
41125
- },
41126
- "iservice365-resident-mobile-app"
41127
- );
41128
- }
41129
- static async prelovedMarketplacePostCreation(payload) {
41130
- await send(
41131
- toStringArray(payload.to),
41132
- "Preloved Marketplace",
41133
- `New preloved marketplace post added.`,
41134
- {
41135
- prelovedId: payload.prelovedId.toString(),
41136
- status: payload.status,
41137
- module: "prelovedMarketplace",
41138
- screen: "/(user)/(marketplace)/prelovedPostInfo",
41139
- params: {
41140
- id: payload.prelovedId.toString()
41141
- }
41142
- },
41143
- "iservice365-resident-mobile-app"
41144
- );
41145
- }
41146
- };
41147
-
41148
- // src/services/bulletin-board.service.ts
41149
41315
  function useBulletinBoardService() {
41150
41316
  const {
41151
41317
  add: _add,
@@ -41212,6 +41378,12 @@ function useBulletinBoardService() {
41212
41378
  status: bulletinBoardStatus
41213
41379
  });
41214
41380
  }
41381
+ NotificationService.bulletinBoardCreatedForMA({
41382
+ to: userIds,
41383
+ bulletinId: bulletinBoardId,
41384
+ subject: "Bulletin Board",
41385
+ status: bulletinBoardStatus
41386
+ });
41215
41387
  }
41216
41388
  await session?.commitTransaction();
41217
41389
  return "Successfully added bulletin board.";
@@ -43174,11 +43346,27 @@ function useEventManagementService() {
43174
43346
  updateEventManagementById: _updateEventManagementById,
43175
43347
  processCompletedEvents: _processCompletedEvents
43176
43348
  } = useEventManagementRepo();
43349
+ const { getUsersBySiteId } = useMemberRepo();
43177
43350
  async function add(value) {
43178
43351
  const session = useAtlas74.getClient()?.startSession();
43179
43352
  try {
43180
43353
  session?.startTransaction();
43181
- await _add(value, session);
43354
+ const response = await _add(value, session);
43355
+ console.log("response", response);
43356
+ const users = await getUsersBySiteId({
43357
+ status: "active",
43358
+ siteId: value.site
43359
+ });
43360
+ if (users?.length > 0) {
43361
+ const userIds = Array.from(
43362
+ new Set(users.map((item) => item.user.toString()))
43363
+ );
43364
+ NotificationService.eventCreatedForMA({
43365
+ to: userIds,
43366
+ eventId: response,
43367
+ status: value.status
43368
+ });
43369
+ }
43182
43370
  await session?.commitTransaction();
43183
43371
  return "Successfully added event.";
43184
43372
  } catch (error) {
@@ -56685,73 +56873,6 @@ var Period = /* @__PURE__ */ ((Period2) => {
56685
56873
  Period2["THIS_MONTH"] = "thisMonth";
56686
56874
  return Period2;
56687
56875
  })(Period || {});
56688
- function getPeriodRangeWithPrevious(period) {
56689
- const now = /* @__PURE__ */ new Date();
56690
- let currentStart = /* @__PURE__ */ new Date();
56691
- let currentEnd = /* @__PURE__ */ new Date();
56692
- let previousStart = /* @__PURE__ */ new Date();
56693
- let previousEnd = /* @__PURE__ */ new Date();
56694
- if (period === "today" /* TODAY */) {
56695
- currentStart.setHours(0, 0, 0, 0);
56696
- currentEnd.setHours(23, 59, 59, 999);
56697
- previousStart = new Date(currentStart);
56698
- previousStart.setDate(previousStart.getDate() - 1);
56699
- previousEnd = new Date(currentEnd);
56700
- previousEnd.setDate(previousEnd.getDate() - 1);
56701
- } else if (period === "thisWeek" /* THIS_WEEK */) {
56702
- const day = now.getDay();
56703
- const diffToMonday = day === 0 ? -6 : 1 - day;
56704
- currentStart = new Date(now);
56705
- currentStart.setDate(now.getDate() + diffToMonday);
56706
- currentStart.setHours(0, 0, 0, 0);
56707
- currentEnd = new Date(currentStart);
56708
- currentEnd.setDate(currentStart.getDate() + 6);
56709
- currentEnd.setHours(23, 59, 59, 999);
56710
- previousStart = new Date(currentStart);
56711
- previousStart.setDate(previousStart.getDate() - 7);
56712
- previousEnd = new Date(currentEnd);
56713
- previousEnd.setDate(previousEnd.getDate() - 7);
56714
- } else if (period === "thisMonth" /* THIS_MONTH */) {
56715
- currentStart = new Date(now.getFullYear(), now.getMonth(), 1);
56716
- currentEnd = new Date(
56717
- now.getFullYear(),
56718
- now.getMonth() + 1,
56719
- 0,
56720
- 23,
56721
- 59,
56722
- 59,
56723
- 999
56724
- );
56725
- previousStart = new Date(now.getFullYear(), now.getMonth() - 1, 1);
56726
- previousEnd = new Date(
56727
- now.getFullYear(),
56728
- now.getMonth(),
56729
- 0,
56730
- 23,
56731
- 59,
56732
- 59,
56733
- 999
56734
- );
56735
- } else {
56736
- throw new BadRequestError182("Invalid period.");
56737
- }
56738
- return {
56739
- current: {
56740
- start: currentStart.toISOString(),
56741
- end: currentEnd.toISOString()
56742
- },
56743
- previous: {
56744
- start: previousStart.toISOString(),
56745
- end: previousEnd.toISOString()
56746
- }
56747
- };
56748
- }
56749
- function calculatePercentage(current, previous) {
56750
- if (previous === 0) {
56751
- return current === 0 ? 0 : 100;
56752
- }
56753
- return Number(((current - previous) / previous * 100).toFixed(2));
56754
- }
56755
56876
  function useNewDashboardRepo() {
56756
56877
  const db = useAtlas100.getDb();
56757
56878
  if (!db) {
@@ -57260,7 +57381,8 @@ function useNewDashboardRepo() {
57260
57381
  currentlyOnSiteCount,
57261
57382
  facilityReport,
57262
57383
  yesterdayFacilityReport,
57263
- todayFacilityReport
57384
+ todayFacilityReport,
57385
+ workOrderStatusReport
57264
57386
  ] = await Promise.all([
57265
57387
  workOrderCollection.aggregate([
57266
57388
  {
@@ -57450,6 +57572,20 @@ function useNewDashboardRepo() {
57450
57572
  }
57451
57573
  },
57452
57574
  { $count: "count" }
57575
+ ]).toArray(),
57576
+ workOrderCollection.aggregate([
57577
+ {
57578
+ $match: {
57579
+ site: { $in: [siteIdObj, siteId] },
57580
+ createdAt: periodRange
57581
+ }
57582
+ },
57583
+ {
57584
+ $group: {
57585
+ _id: "$status",
57586
+ count: { $sum: 1 }
57587
+ }
57588
+ }
57453
57589
  ]).toArray()
57454
57590
  ]);
57455
57591
  const wFacet = workOrderReport[0] ?? { total: [], inProgress: [] };
@@ -57458,6 +57594,23 @@ function useNewDashboardRepo() {
57458
57594
  ongoing: [],
57459
57595
  waitingApproval: []
57460
57596
  };
57597
+ const workOrderStatus = {
57598
+ pending: 0,
57599
+ inProgress: 0,
57600
+ completed: 0
57601
+ };
57602
+ for (const item of workOrderStatusReport || []) {
57603
+ const rawStatus = String(item._id || "").toLowerCase().trim();
57604
+ if (rawStatus === "to-do" || rawStatus === "for-review") {
57605
+ workOrderStatus.pending += item.count || 0;
57606
+ } else if (rawStatus === "in-progress") {
57607
+ workOrderStatus.inProgress += item.count || 0;
57608
+ } else if (rawStatus === "completed") {
57609
+ workOrderStatus.completed += item.count || 0;
57610
+ } else {
57611
+ workOrderStatus.pending += item.count || 0;
57612
+ }
57613
+ }
57461
57614
  const data = {
57462
57615
  openWorkOrder: {
57463
57616
  count: wFacet.total[0]?.count ?? 0,
@@ -57492,6 +57645,7 @@ function useNewDashboardRepo() {
57492
57645
  yesterdayFacilityReport[0]?.count ?? 0
57493
57646
  )
57494
57647
  },
57648
+ workOrderStatus,
57495
57649
  upcomingEvents,
57496
57650
  todayReminders,
57497
57651
  todayAttentions
@@ -66191,7 +66345,8 @@ var schemaUpdateChatPreloved = Joi141.object({
66191
66345
  reactions: Joi141.string().optional().allow("", null)
66192
66346
  });
66193
66347
  var schemaChatPreloved = Joi141.object({
66194
- channelId: Joi141.string().hex().length(24).required(),
66348
+ channelId: Joi141.string().hex().length(24).optional().allow("", null),
66349
+ receiverId: Joi141.string().hex().length(24).optional().allow("", null),
66195
66350
  senderId: Joi141.string().hex().length(24).required(),
66196
66351
  postId: Joi141.string().hex().length(24).optional().allow("", null),
66197
66352
  message: schemaMessage.required(),
@@ -66238,7 +66393,7 @@ function MChatPreloved(value) {
66238
66393
  }
66239
66394
  return {
66240
66395
  _id: new ObjectId145(),
66241
- channelId: value.channelId ?? "",
66396
+ channelId: value.channelId ?? null,
66242
66397
  senderId: value.senderId ?? "",
66243
66398
  postId: value.postId ?? null,
66244
66399
  message: {
@@ -66320,10 +66475,6 @@ function useChatPrelovedRepo() {
66320
66475
  return { add, updateById, deleteById };
66321
66476
  }
66322
66477
 
66323
- // src/controllers/chat-preloved.controller.ts
66324
- import { BadRequestError as BadRequestError222, logger as logger192 } from "@7365admin1/node-server-utils";
66325
- import Joi143 from "joi";
66326
-
66327
66478
  // src/services/chat-preloved.service.ts
66328
66479
  import { BadRequestError as BadRequestError221, InternalServerError as InternalServerError81, useAtlas as useAtlas126 } from "@7365admin1/node-server-utils";
66329
66480
 
@@ -66477,7 +66628,130 @@ function useChannelPrelovedRepo() {
66477
66628
  throw error;
66478
66629
  }
66479
66630
  }
66480
- return { add, getByParticipants, getChannelMessages };
66631
+ async function getChatLists(currentUserId, page = 1, limit = 10, search) {
66632
+ const normalizedPage = page > 0 ? page - 1 : 0;
66633
+ const normalizedLimit = limit || 10;
66634
+ const _currentUserId = new ObjectId148(currentUserId);
66635
+ const escapedSearch = search ? search.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") : null;
66636
+ const pipeline = [
66637
+ {
66638
+ $match: {
66639
+ $or: [{ receiverId: _currentUserId }, { senderId: _currentUserId }]
66640
+ }
66641
+ },
66642
+ {
66643
+ $lookup: {
66644
+ from: "users",
66645
+ localField: "senderId",
66646
+ foreignField: "_id",
66647
+ pipeline: [
66648
+ {
66649
+ $project: {
66650
+ name: 1,
66651
+ profile: 1,
66652
+ type: 1
66653
+ }
66654
+ }
66655
+ ],
66656
+ as: "senderId"
66657
+ }
66658
+ },
66659
+ { $unwind: { path: "$senderId", preserveNullAndEmptyArrays: true } },
66660
+ {
66661
+ $lookup: {
66662
+ from: "post-preloved",
66663
+ localField: "postId",
66664
+ foreignField: "_id",
66665
+ pipeline: [
66666
+ {
66667
+ $project: {
66668
+ title: 1,
66669
+ description: 1,
66670
+ attachments: 1,
66671
+ price: 1,
66672
+ status: 1,
66673
+ createdBy: 1,
66674
+ reserverId: 1
66675
+ }
66676
+ }
66677
+ ],
66678
+ as: "postDetails"
66679
+ }
66680
+ },
66681
+ { $unwind: { path: "$postDetails", preserveNullAndEmptyArrays: true } },
66682
+ ...escapedSearch ? [
66683
+ {
66684
+ $match: {
66685
+ $or: [
66686
+ {
66687
+ "senderId.name": {
66688
+ $regex: new RegExp(escapedSearch, "i")
66689
+ }
66690
+ },
66691
+ {
66692
+ "postDetails.title": {
66693
+ $regex: new RegExp(escapedSearch, "i")
66694
+ }
66695
+ }
66696
+ ]
66697
+ }
66698
+ }
66699
+ ] : [],
66700
+ {
66701
+ $lookup: {
66702
+ from: "chat-preloved",
66703
+ localField: "_id",
66704
+ foreignField: "channelId",
66705
+ pipeline: [
66706
+ { $match: { deletedAt: null } },
66707
+ { $sort: { createdAt: -1 } },
66708
+ { $limit: 1 }
66709
+ ],
66710
+ as: "latestChat"
66711
+ }
66712
+ },
66713
+ { $unwind: { path: "$latestChat", preserveNullAndEmptyArrays: true } },
66714
+ { $addFields: { lastMessageDate: "$latestChat.createdAt" } },
66715
+ {
66716
+ $lookup: {
66717
+ from: "bid-preloved",
66718
+ localField: "postId",
66719
+ foreignField: "postId",
66720
+ pipeline: [
66721
+ { $sort: { createdAt: -1 } },
66722
+ { $limit: 1 },
66723
+ { $project: { price: 1, message: 1, status: 1, type: 1 } }
66724
+ ],
66725
+ as: "latestBidDetails"
66726
+ }
66727
+ },
66728
+ {
66729
+ $unwind: {
66730
+ path: "$latestBidDetails",
66731
+ preserveNullAndEmptyArrays: true
66732
+ }
66733
+ },
66734
+ { $sort: { lastMessageDate: -1 } },
66735
+ {
66736
+ $facet: {
66737
+ totalCount: [{ $count: "count" }],
66738
+ items: [
66739
+ { $skip: normalizedPage * normalizedLimit },
66740
+ { $limit: normalizedLimit }
66741
+ ]
66742
+ }
66743
+ }
66744
+ ];
66745
+ try {
66746
+ const result = await collection.aggregate(pipeline).toArray();
66747
+ const totalCount = result[0].totalCount[0]?.count ?? 0;
66748
+ const items = result[0].items;
66749
+ return paginate63(items, normalizedPage, normalizedLimit, totalCount);
66750
+ } catch (error) {
66751
+ throw error;
66752
+ }
66753
+ }
66754
+ return { add, getByParticipants, getChatLists, getChannelMessages };
66481
66755
  }
66482
66756
 
66483
66757
  // src/services/chat-preloved.service.ts
@@ -66531,6 +66805,8 @@ function useChatPrelovedService() {
66531
66805
  }
66532
66806
 
66533
66807
  // src/controllers/chat-preloved.controller.ts
66808
+ import { BadRequestError as BadRequestError222, logger as logger192 } from "@7365admin1/node-server-utils";
66809
+ import Joi143 from "joi";
66534
66810
  function useChatPrelovedController() {
66535
66811
  const { add: _add } = useChatPrelovedService();
66536
66812
  const { updateById: _updateById, deleteById: _deleteById } = useChatPrelovedRepo();
@@ -66595,7 +66871,12 @@ function useChatPrelovedController() {
66595
66871
  import { BadRequestError as BadRequestError223, logger as logger193 } from "@7365admin1/node-server-utils";
66596
66872
  import Joi144 from "joi";
66597
66873
  function useChannelPrelovedController() {
66598
- const { add: _add, getChannelMessages: _getChannelMessages } = useChannelPrelovedRepo();
66874
+ const {
66875
+ add: _add,
66876
+ getByParticipants: _getByParticipants,
66877
+ getChatLists: _getChatLists,
66878
+ getChannelMessages: _getChannelMessages
66879
+ } = useChannelPrelovedRepo();
66599
66880
  async function add(req, res, next) {
66600
66881
  const { error, value } = schemaChannelPreloved.validate(req.body, {
66601
66882
  abortEarly: false
@@ -66632,9 +66913,7 @@ function useChannelPrelovedController() {
66632
66913
  next(new BadRequestError223(paramError.message));
66633
66914
  return;
66634
66915
  }
66635
- const { error: queryError, value: query } = querySchema.validate(
66636
- req.query
66637
- );
66916
+ const { error: queryError, value: query } = querySchema.validate(req.query);
66638
66917
  if (queryError) {
66639
66918
  logger193.log({ level: "error", message: queryError.message });
66640
66919
  next(new BadRequestError223(queryError.message));
@@ -66654,61 +66933,253 @@ function useChannelPrelovedController() {
66654
66933
  next(error);
66655
66934
  }
66656
66935
  }
66657
- return { add, getChannelMessages };
66936
+ async function getChannel(req, res, next) {
66937
+ const querySchema = Joi144.object({
66938
+ postId: Joi144.string().hex().length(24).required(),
66939
+ receiverId: Joi144.string().hex().length(24).required(),
66940
+ senderId: Joi144.string().hex().length(24).required()
66941
+ });
66942
+ const { error, value } = querySchema.validate(req.query);
66943
+ if (error) {
66944
+ logger193.log({ level: "error", message: error.message });
66945
+ next(new BadRequestError223(error.message));
66946
+ return;
66947
+ }
66948
+ try {
66949
+ const data = await _getByParticipants(
66950
+ value.senderId,
66951
+ value.receiverId,
66952
+ value.postId
66953
+ );
66954
+ res.status(200).json(data);
66955
+ } catch (error2) {
66956
+ logger193.log({ level: "error", message: error2.message });
66957
+ next(error2);
66958
+ }
66959
+ }
66960
+ async function getChatLists(req, res, next) {
66961
+ const querySchema = Joi144.object({
66962
+ currentUserId: Joi144.string().hex().length(24).required(),
66963
+ page: Joi144.number().integer().min(1).default(1),
66964
+ limit: Joi144.number().integer().min(1).max(100).default(10),
66965
+ search: Joi144.string().optional().allow("", null)
66966
+ });
66967
+ const { error, value } = querySchema.validate(req.query);
66968
+ if (error) {
66969
+ logger193.log({ level: "error", message: error.message });
66970
+ next(new BadRequestError223(error.message));
66971
+ return;
66972
+ }
66973
+ try {
66974
+ const data = await _getChatLists(
66975
+ value.currentUserId,
66976
+ value.page,
66977
+ value.limit,
66978
+ value.search || void 0
66979
+ );
66980
+ res.status(200).json(data);
66981
+ } catch (error2) {
66982
+ logger193.log({ level: "error", message: error2.message });
66983
+ next(error2);
66984
+ }
66985
+ }
66986
+ return { add, getChannel, getChatLists, getChannelMessages };
66658
66987
  }
66659
66988
 
66660
- // src/models/online-forms-v2.model.ts
66989
+ // src/models/bid-preloved.model.ts
66661
66990
  import Joi145 from "joi";
66662
66991
  import { ObjectId as ObjectId149 } from "mongodb";
66992
+ var BidType = /* @__PURE__ */ ((BidType2) => {
66993
+ BidType2["BID"] = "bid";
66994
+ BidType2["RESERVE"] = "reserve";
66995
+ return BidType2;
66996
+ })(BidType || {});
66997
+ var BidStatus = /* @__PURE__ */ ((BidStatus3) => {
66998
+ BidStatus3["PENDING"] = "pending";
66999
+ BidStatus3["ACCEPTED"] = "accepted";
67000
+ BidStatus3["RESERVED"] = "reserved";
67001
+ BidStatus3["CANCELLED"] = "cancelled";
67002
+ return BidStatus3;
67003
+ })(BidStatus || {});
67004
+ var schemaBidPreloved = Joi145.object({
67005
+ type: Joi145.string().valid(...Object.values(BidType)).required(),
67006
+ postId: Joi145.string().hex().length(24).required(),
67007
+ price: Joi145.when("type", {
67008
+ is: "bid" /* BID */,
67009
+ then: Joi145.number().required(),
67010
+ otherwise: Joi145.number().optional().allow(null)
67011
+ }),
67012
+ message: Joi145.string().optional().allow("", null),
67013
+ buyerId: Joi145.string().hex().length(24).optional().allow("", null),
67014
+ status: Joi145.string().valid(...Object.values(BidStatus)).optional().default("pending" /* PENDING */)
67015
+ });
67016
+ var schemaUpdateBidPreloved = Joi145.object({
67017
+ status: Joi145.string().valid(...Object.values(BidStatus)).required()
67018
+ });
67019
+ function MBidPreloved(value) {
67020
+ const { error } = schemaBidPreloved.validate(value);
67021
+ if (error)
67022
+ throw new Error(error.details[0].message);
67023
+ if (value.postId && typeof value.postId === "string")
67024
+ value.postId = new ObjectId149(value.postId);
67025
+ if (value.buyerId && typeof value.buyerId === "string")
67026
+ value.buyerId = new ObjectId149(value.buyerId);
67027
+ return {
67028
+ _id: new ObjectId149(),
67029
+ price: value.price ?? null,
67030
+ message: value.message ?? "",
67031
+ status: value.status ?? "pending" /* PENDING */,
67032
+ type: value.type,
67033
+ postId: value.postId,
67034
+ buyerId: value.buyerId ?? null,
67035
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
67036
+ updatedAt: null
67037
+ };
67038
+ }
67039
+
67040
+ // src/repositories/bid-preloved.repo.ts
67041
+ import {
67042
+ InternalServerError as InternalServerError82,
67043
+ NotFoundError as NotFoundError61,
67044
+ useAtlas as useAtlas127
67045
+ } from "@7365admin1/node-server-utils";
67046
+ import { ObjectId as ObjectId150 } from "mongodb";
67047
+ function useBidPrelovedRepo() {
67048
+ const db = useAtlas127.getDb();
67049
+ if (!db)
67050
+ throw new InternalServerError82("Unable to connect to server.");
67051
+ const collection = db.collection("bid-preloved");
67052
+ async function add(value, session) {
67053
+ try {
67054
+ const doc = MBidPreloved(value);
67055
+ const res = await collection.insertOne(doc, { session });
67056
+ return res.insertedId;
67057
+ } catch (error) {
67058
+ throw error;
67059
+ }
67060
+ }
67061
+ async function updateStatus(_id, status) {
67062
+ const objectId2 = typeof _id === "string" ? new ObjectId150(_id) : _id;
67063
+ const existing = await collection.findOne({ _id: objectId2 });
67064
+ if (!existing)
67065
+ throw new NotFoundError61("Bid not found.");
67066
+ const res = await collection.updateOne(
67067
+ { _id: objectId2 },
67068
+ { $set: { status, updatedAt: (/* @__PURE__ */ new Date()).toISOString() } }
67069
+ );
67070
+ if (res.modifiedCount === 0)
67071
+ throw new InternalServerError82("Unable to update bid.");
67072
+ return "Bid updated successfully.";
67073
+ }
67074
+ return { add, updateStatus };
67075
+ }
67076
+
67077
+ // src/controllers/bid-preloved.controller.ts
67078
+ import { BadRequestError as BadRequestError224, logger as logger194 } from "@7365admin1/node-server-utils";
67079
+ import Joi146 from "joi";
67080
+ function useBidPrelovedController() {
67081
+ const { add: _add, updateStatus: _updateStatus } = useBidPrelovedRepo();
67082
+ async function add(req, res, next) {
67083
+ const { error, value } = schemaBidPreloved.validate(req.body, {
67084
+ abortEarly: false
67085
+ });
67086
+ if (error) {
67087
+ const messages = error.details.map((d) => d.message).join(", ");
67088
+ logger194.log({ level: "error", message: messages });
67089
+ next(new BadRequestError224(messages));
67090
+ return;
67091
+ }
67092
+ try {
67093
+ const data = await _add(value);
67094
+ res.status(201).json(data);
67095
+ } catch (error2) {
67096
+ logger194.log({ level: "error", message: error2.message });
67097
+ next(error2);
67098
+ }
67099
+ }
67100
+ async function updateStatus(req, res, next) {
67101
+ const paramsSchema = Joi146.object({
67102
+ id: Joi146.string().hex().length(24).required()
67103
+ });
67104
+ const { error: paramError, value: params } = paramsSchema.validate(
67105
+ req.params
67106
+ );
67107
+ if (paramError) {
67108
+ logger194.log({ level: "error", message: paramError.message });
67109
+ next(new BadRequestError224(paramError.message));
67110
+ return;
67111
+ }
67112
+ const { error: bodyError, value: body } = schemaUpdateBidPreloved.validate(
67113
+ req.body
67114
+ );
67115
+ if (bodyError) {
67116
+ logger194.log({ level: "error", message: bodyError.message });
67117
+ next(new BadRequestError224(bodyError.message));
67118
+ return;
67119
+ }
67120
+ try {
67121
+ const data = await _updateStatus(params.id, body.status);
67122
+ res.status(200).json(data);
67123
+ } catch (error) {
67124
+ logger194.log({ level: "error", message: error.message });
67125
+ next(error);
67126
+ }
67127
+ }
67128
+ return { add, updateStatus };
67129
+ }
67130
+
67131
+ // src/models/online-forms-v2.model.ts
67132
+ import Joi147 from "joi";
67133
+ import { ObjectId as ObjectId151 } from "mongodb";
66663
67134
  var FormEntryStatus = /* @__PURE__ */ ((FormEntryStatus2) => {
66664
67135
  FormEntryStatus2["ACTIVE"] = "active";
66665
67136
  FormEntryStatus2["INACTIVE"] = "inactive";
66666
67137
  FormEntryStatus2["DELETED"] = "deleted";
66667
67138
  return FormEntryStatus2;
66668
67139
  })(FormEntryStatus || {});
66669
- var schemaFormEntry = Joi145.object({
66670
- _id: Joi145.string().hex().optional().allow("", null),
66671
- formType: Joi145.string().required(),
66672
- block: Joi145.string().optional().allow(null, ""),
66673
- level: Joi145.string().optional().allow(null, ""),
66674
- unit: Joi145.string().optional().allow(null, ""),
66675
- name: Joi145.string().optional().allow(null, ""),
66676
- phoneNumber: Joi145.string().optional().allow(null, ""),
66677
- createdBy: Joi145.string().required(),
66678
- fields: Joi145.object().pattern(
66679
- Joi145.string(),
66680
- Joi145.alternatives().try(
66681
- Joi145.string(),
66682
- Joi145.number(),
66683
- Joi145.boolean(),
66684
- Joi145.valid(null)
67140
+ var schemaFormEntry = Joi147.object({
67141
+ _id: Joi147.string().hex().optional().allow("", null),
67142
+ formType: Joi147.string().required(),
67143
+ block: Joi147.string().optional().allow(null, ""),
67144
+ level: Joi147.string().optional().allow(null, ""),
67145
+ unit: Joi147.string().optional().allow(null, ""),
67146
+ name: Joi147.string().optional().allow(null, ""),
67147
+ phoneNumber: Joi147.string().optional().allow(null, ""),
67148
+ createdBy: Joi147.string().required(),
67149
+ fields: Joi147.object().pattern(
67150
+ Joi147.string(),
67151
+ Joi147.alternatives().try(
67152
+ Joi147.string(),
67153
+ Joi147.number(),
67154
+ Joi147.boolean(),
67155
+ Joi147.valid(null)
66685
67156
  )
66686
67157
  ).required(),
66687
- status: Joi145.string().optional().allow("", null),
66688
- org: Joi145.string().hex().optional().allow("", null),
66689
- site: Joi145.string().hex().optional().allow("", null),
66690
- createdAt: Joi145.date().optional().allow("", null),
66691
- updatedAt: Joi145.date().optional().allow("", null),
66692
- deletedAt: Joi145.date().optional().allow("", null)
67158
+ status: Joi147.string().optional().allow("", null),
67159
+ org: Joi147.string().hex().optional().allow("", null),
67160
+ site: Joi147.string().hex().optional().allow("", null),
67161
+ createdAt: Joi147.date().optional().allow("", null),
67162
+ updatedAt: Joi147.date().optional().allow("", null),
67163
+ deletedAt: Joi147.date().optional().allow("", null)
66693
67164
  });
66694
- var schemaUpdateFormEntry = Joi145.object({
66695
- _id: Joi145.string().hex().required(),
66696
- formType: Joi145.string().optional().allow("", null),
66697
- block: Joi145.string().optional().allow(null, ""),
66698
- level: Joi145.string().optional().allow(null, ""),
66699
- unit: Joi145.string().optional().allow(null, ""),
66700
- fields: Joi145.object().pattern(
66701
- Joi145.string(),
66702
- Joi145.alternatives().try(
66703
- Joi145.string(),
66704
- Joi145.number(),
66705
- Joi145.boolean(),
66706
- Joi145.valid(null)
67165
+ var schemaUpdateFormEntry = Joi147.object({
67166
+ _id: Joi147.string().hex().required(),
67167
+ formType: Joi147.string().optional().allow("", null),
67168
+ block: Joi147.string().optional().allow(null, ""),
67169
+ level: Joi147.string().optional().allow(null, ""),
67170
+ unit: Joi147.string().optional().allow(null, ""),
67171
+ fields: Joi147.object().pattern(
67172
+ Joi147.string(),
67173
+ Joi147.alternatives().try(
67174
+ Joi147.string(),
67175
+ Joi147.number(),
67176
+ Joi147.boolean(),
67177
+ Joi147.valid(null)
66707
67178
  )
66708
67179
  ).optional(),
66709
- status: Joi145.string().optional().allow("", null),
66710
- updatedAt: Joi145.date().optional().allow("", null),
66711
- deletedAt: Joi145.date().optional().allow("", null)
67180
+ status: Joi147.string().optional().allow("", null),
67181
+ updatedAt: Joi147.date().optional().allow("", null),
67182
+ deletedAt: Joi147.date().optional().allow("", null)
66712
67183
  });
66713
67184
  function MFormEntry(value) {
66714
67185
  const { error } = schemaFormEntry.validate(value);
@@ -66717,21 +67188,21 @@ function MFormEntry(value) {
66717
67188
  }
66718
67189
  if (value._id && typeof value._id === "string") {
66719
67190
  try {
66720
- value._id = new ObjectId149(value._id);
67191
+ value._id = new ObjectId151(value._id);
66721
67192
  } catch {
66722
67193
  throw new Error("Invalid ID.");
66723
67194
  }
66724
67195
  }
66725
67196
  if (value.org && typeof value.org === "string") {
66726
67197
  try {
66727
- value.org = new ObjectId149(value.org);
67198
+ value.org = new ObjectId151(value.org);
66728
67199
  } catch {
66729
67200
  throw new Error("Invalid org ID.");
66730
67201
  }
66731
67202
  }
66732
67203
  if (value.site && typeof value.site === "string") {
66733
67204
  try {
66734
- value.site = new ObjectId149(value.site);
67205
+ value.site = new ObjectId151(value.site);
66735
67206
  } catch {
66736
67207
  throw new Error("Invalid site ID.");
66737
67208
  }
@@ -66753,55 +67224,55 @@ function MFormEntry(value) {
66753
67224
  deletedAt: value.deletedAt ?? null
66754
67225
  };
66755
67226
  }
66756
- var residentFormEntry = Joi145.object({
66757
- _id: Joi145.string().hex().optional().allow("", null),
66758
- typeOfForm: Joi145.string().optional().allow("", null),
66759
- unitNumber: Joi145.string().optional().allow(null, ""),
66760
- fields: Joi145.object().pattern(
66761
- Joi145.string(),
66762
- Joi145.alternatives().try(
66763
- Joi145.string(),
66764
- Joi145.number(),
66765
- Joi145.boolean(),
66766
- Joi145.valid(null)
67227
+ var residentFormEntry = Joi147.object({
67228
+ _id: Joi147.string().hex().optional().allow("", null),
67229
+ typeOfForm: Joi147.string().optional().allow("", null),
67230
+ unitNumber: Joi147.string().optional().allow(null, ""),
67231
+ fields: Joi147.object().pattern(
67232
+ Joi147.string(),
67233
+ Joi147.alternatives().try(
67234
+ Joi147.string(),
67235
+ Joi147.number(),
67236
+ Joi147.boolean(),
67237
+ Joi147.valid(null)
66767
67238
  )
66768
67239
  ).optional().allow(null, ""),
66769
- status: Joi145.string().optional().allow("", null),
66770
- org: Joi145.string().hex().optional().allow("", null),
66771
- site: Joi145.string().hex().optional().allow("", null),
66772
- userId: Joi145.string().hex().optional().allow("", null),
66773
- createdAt: Joi145.date().optional().allow("", null),
66774
- updatedAt: Joi145.date().optional().allow("", null),
66775
- deletedAt: Joi145.date().optional().allow("", null),
66776
- remarks: Joi145.string().optional().allow("", null),
66777
- managementValues: Joi145.object().pattern(
66778
- Joi145.string(),
66779
- Joi145.alternatives().try(
66780
- Joi145.string(),
66781
- Joi145.number(),
66782
- Joi145.boolean(),
66783
- Joi145.valid(null)
67240
+ status: Joi147.string().optional().allow("", null),
67241
+ org: Joi147.string().hex().optional().allow("", null),
67242
+ site: Joi147.string().hex().optional().allow("", null),
67243
+ userId: Joi147.string().hex().optional().allow("", null),
67244
+ createdAt: Joi147.date().optional().allow("", null),
67245
+ updatedAt: Joi147.date().optional().allow("", null),
67246
+ deletedAt: Joi147.date().optional().allow("", null),
67247
+ remarks: Joi147.string().optional().allow("", null),
67248
+ managementValues: Joi147.object().pattern(
67249
+ Joi147.string(),
67250
+ Joi147.alternatives().try(
67251
+ Joi147.string(),
67252
+ Joi147.number(),
67253
+ Joi147.boolean(),
67254
+ Joi147.valid(null)
66784
67255
  )
66785
67256
  ).optional().allow(null, "")
66786
67257
  });
66787
67258
 
66788
67259
  // src/repositories/online-forms-v2.repository.ts
66789
67260
  import {
66790
- BadRequestError as BadRequestError224,
66791
- InternalServerError as InternalServerError82,
66792
- logger as logger194,
67261
+ BadRequestError as BadRequestError225,
67262
+ InternalServerError as InternalServerError83,
67263
+ logger as logger195,
66793
67264
  makeCacheKey as makeCacheKey65,
66794
- NotFoundError as NotFoundError61,
67265
+ NotFoundError as NotFoundError62,
66795
67266
  paginate as paginate64,
66796
- useAtlas as useAtlas127,
67267
+ useAtlas as useAtlas128,
66797
67268
  useCache as useCache69
66798
67269
  } from "@7365admin1/node-server-utils";
66799
- import { ObjectId as ObjectId150 } from "mongodb";
67270
+ import { ObjectId as ObjectId152 } from "mongodb";
66800
67271
  var online_forms_namespace_collection = "online-forms";
66801
67272
  function useFormEntryRepo() {
66802
- const db = useAtlas127.getDb();
67273
+ const db = useAtlas128.getDb();
66803
67274
  if (!db) {
66804
- throw new InternalServerError82("Unable to connect to server.");
67275
+ throw new InternalServerError83("Unable to connect to server.");
66805
67276
  }
66806
67277
  const collection = db.collection(online_forms_namespace_collection);
66807
67278
  const { delNamespace, getCache, setCache } = useCache69(
@@ -66813,7 +67284,7 @@ function useFormEntryRepo() {
66813
67284
  name: "text"
66814
67285
  });
66815
67286
  } catch (error) {
66816
- throw new InternalServerError82(
67287
+ throw new InternalServerError83(
66817
67288
  "Failed to create text index on online form."
66818
67289
  );
66819
67290
  }
@@ -66823,11 +67294,11 @@ function useFormEntryRepo() {
66823
67294
  value = MFormEntry(value);
66824
67295
  const res = await collection.insertOne(value, { session });
66825
67296
  delNamespace().then(() => {
66826
- logger194.info(
67297
+ logger195.info(
66827
67298
  `Cache cleared for namespace: ${online_forms_namespace_collection}`
66828
67299
  );
66829
67300
  }).catch((err) => {
66830
- logger194.error(
67301
+ logger195.error(
66831
67302
  `Failed to clear cache for namespace: ${online_forms_namespace_collection}`,
66832
67303
  err
66833
67304
  );
@@ -66836,7 +67307,7 @@ function useFormEntryRepo() {
66836
67307
  } catch (error) {
66837
67308
  const isDuplicated = error.message.includes("duplicate");
66838
67309
  if (isDuplicated) {
66839
- throw new BadRequestError224("Online Form already exists.");
67310
+ throw new BadRequestError225("Online Form already exists.");
66840
67311
  }
66841
67312
  throw error;
66842
67313
  }
@@ -66852,8 +67323,8 @@ function useFormEntryRepo() {
66852
67323
  }) {
66853
67324
  page = page > 0 ? page - 1 : 0;
66854
67325
  sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
66855
- site = new ObjectId150(site);
66856
- org = new ObjectId150(org);
67326
+ site = new ObjectId152(site);
67327
+ org = new ObjectId152(org);
66857
67328
  const cacheOptions = {
66858
67329
  page,
66859
67330
  limit,
@@ -66879,7 +67350,7 @@ function useFormEntryRepo() {
66879
67350
  );
66880
67351
  const cachedData = await getCache(cacheKey);
66881
67352
  if (cachedData) {
66882
- logger194.info(`Cache hit for key: ${cacheKey}`);
67353
+ logger195.info(`Cache hit for key: ${cacheKey}`);
66883
67354
  return cachedData;
66884
67355
  }
66885
67356
  try {
@@ -66887,14 +67358,30 @@ function useFormEntryRepo() {
66887
67358
  { $match: query },
66888
67359
  { $sort: sort },
66889
67360
  { $skip: page * limit },
66890
- { $limit: limit }
67361
+ { $limit: limit },
67362
+ {
67363
+ $lookup: {
67364
+ from: "users",
67365
+ localField: "userId",
67366
+ foreignField: "_id",
67367
+ as: "user",
67368
+ pipeline: [{ $project: { name: 1 } }]
67369
+ }
67370
+ },
67371
+ { $unwind: { path: "$user", preserveNullAndEmptyArrays: true } },
67372
+ {
67373
+ $addFields: {
67374
+ name: { $ifNull: ["$user.name", "$name"] }
67375
+ }
67376
+ },
67377
+ { $project: { user: 0 } }
66891
67378
  ]).toArray();
66892
67379
  const length = await collection.countDocuments(query);
66893
67380
  const data = paginate64(items, page, limit, length);
66894
67381
  setCache(cacheKey, data, 15 * 60).then(() => {
66895
- logger194.info(`Cache set for key: ${cacheKey}`);
67382
+ logger195.info(`Cache set for key: ${cacheKey}`);
66896
67383
  }).catch((err) => {
66897
- logger194.error(`Failed to set cache for key: ${cacheKey}`, err);
67384
+ logger195.error(`Failed to set cache for key: ${cacheKey}`, err);
66898
67385
  });
66899
67386
  return data;
66900
67387
  } catch (error) {
@@ -66905,24 +67392,24 @@ function useFormEntryRepo() {
66905
67392
  const cacheKey = makeCacheKey65(online_forms_namespace_collection, { _id });
66906
67393
  const cachedData = await getCache(cacheKey);
66907
67394
  if (cachedData) {
66908
- logger194.info(`Cache hit for key: ${cacheKey}`);
67395
+ logger195.info(`Cache hit for key: ${cacheKey}`);
66909
67396
  return cachedData;
66910
67397
  }
66911
67398
  try {
66912
- _id = new ObjectId150(_id);
67399
+ _id = new ObjectId152(_id);
66913
67400
  } catch (error) {
66914
- throw new BadRequestError224("Invalid online form ID format.");
67401
+ throw new BadRequestError225("Invalid online form ID format.");
66915
67402
  }
66916
67403
  const query = { _id, status: { $ne: "deleted" } };
66917
67404
  try {
66918
67405
  const [data] = await collection.aggregate([{ $match: query }]).toArray();
66919
67406
  if (!data) {
66920
- throw new NotFoundError61("Document not found.");
67407
+ throw new NotFoundError62("Document not found.");
66921
67408
  }
66922
67409
  setCache(cacheKey, data, 15 * 60).then(() => {
66923
- logger194.info(`Cache set for key: ${cacheKey}`);
67410
+ logger195.info(`Cache set for key: ${cacheKey}`);
66924
67411
  }).catch((err) => {
66925
- logger194.error(`Failed to set cache for key: ${cacheKey}`, err);
67412
+ logger195.error(`Failed to set cache for key: ${cacheKey}`, err);
66926
67413
  });
66927
67414
  return data;
66928
67415
  } catch (error) {
@@ -66931,9 +67418,9 @@ function useFormEntryRepo() {
66931
67418
  }
66932
67419
  async function updateFormEntryById(_id, value) {
66933
67420
  try {
66934
- _id = new ObjectId150(_id);
67421
+ _id = new ObjectId152(_id);
66935
67422
  } catch (error) {
66936
- throw new BadRequestError224("Invalid online form ID format.");
67423
+ throw new BadRequestError225("Invalid online form ID format.");
66937
67424
  }
66938
67425
  try {
66939
67426
  const updateValue = {
@@ -66942,14 +67429,14 @@ function useFormEntryRepo() {
66942
67429
  };
66943
67430
  const res = await collection.updateOne({ _id }, { $set: updateValue });
66944
67431
  if (res.modifiedCount === 0) {
66945
- throw new InternalServerError82("Unable to update online form.");
67432
+ throw new InternalServerError83("Unable to update online form.");
66946
67433
  }
66947
67434
  delNamespace().then(() => {
66948
- logger194.info(
67435
+ logger195.info(
66949
67436
  `Cache cleared for namespace: ${online_forms_namespace_collection}`
66950
67437
  );
66951
67438
  }).catch((err) => {
66952
- logger194.error(
67439
+ logger195.error(
66953
67440
  `Failed to clear cache for namespace: ${online_forms_namespace_collection}`,
66954
67441
  err
66955
67442
  );
@@ -66961,9 +67448,9 @@ function useFormEntryRepo() {
66961
67448
  }
66962
67449
  async function deleteOnlineFormById(_id, session) {
66963
67450
  try {
66964
- _id = new ObjectId150(_id);
67451
+ _id = new ObjectId152(_id);
66965
67452
  } catch (error) {
66966
- throw new BadRequestError224("Invalid online form ID format.");
67453
+ throw new BadRequestError225("Invalid online form ID format.");
66967
67454
  }
66968
67455
  try {
66969
67456
  const updateValue = {
@@ -66977,12 +67464,12 @@ function useFormEntryRepo() {
66977
67464
  { session }
66978
67465
  );
66979
67466
  if (res.modifiedCount === 0) {
66980
- throw new InternalServerError82("Unable to delete online form.");
67467
+ throw new InternalServerError83("Unable to delete online form.");
66981
67468
  }
66982
67469
  delNamespace().then(() => {
66983
- logger194.info(`Cache cleared for namespace: ${online_forms_namespace_collection}`);
67470
+ logger195.info(`Cache cleared for namespace: ${online_forms_namespace_collection}`);
66984
67471
  }).catch((err) => {
66985
- logger194.error(
67472
+ logger195.error(
66986
67473
  `Failed to clear cache for namespace: ${online_forms_namespace_collection}`,
66987
67474
  err
66988
67475
  );
@@ -66994,16 +67481,16 @@ function useFormEntryRepo() {
66994
67481
  }
66995
67482
  async function addResidentForm(value, session) {
66996
67483
  try {
66997
- value.site = new ObjectId150(value.site);
66998
- value.org = new ObjectId150(value.org);
66999
- value.userId = new ObjectId150(value.userId);
67484
+ value.site = new ObjectId152(value.site);
67485
+ value.org = new ObjectId152(value.org);
67486
+ value.userId = new ObjectId152(value.userId);
67000
67487
  const res = await collection.insertOne(value, { session });
67001
67488
  delNamespace().then(() => {
67002
- logger194.info(
67489
+ logger195.info(
67003
67490
  `Cache cleared for namespace: ${online_forms_namespace_collection}`
67004
67491
  );
67005
67492
  }).catch((err) => {
67006
- logger194.error(
67493
+ logger195.error(
67007
67494
  `Failed to clear cache for namespace: ${online_forms_namespace_collection}`,
67008
67495
  err
67009
67496
  );
@@ -67012,16 +67499,16 @@ function useFormEntryRepo() {
67012
67499
  } catch (error) {
67013
67500
  const isDuplicated = error.message.includes("duplicate");
67014
67501
  if (isDuplicated) {
67015
- throw new BadRequestError224("Online Form already exists.");
67502
+ throw new BadRequestError225("Online Form already exists.");
67016
67503
  }
67017
67504
  throw error;
67018
67505
  }
67019
67506
  }
67020
67507
  async function residentForm({ userId, site, org }) {
67021
67508
  try {
67022
- const user = new ObjectId150(userId);
67023
- const siteId = new ObjectId150(site);
67024
- const orgId = new ObjectId150(org);
67509
+ const user = new ObjectId152(userId);
67510
+ const siteId = new ObjectId152(site);
67511
+ const orgId = new ObjectId152(org);
67025
67512
  const res = await collection.aggregate([
67026
67513
  {
67027
67514
  $match: {
@@ -67049,8 +67536,8 @@ function useFormEntryRepo() {
67049
67536
  }
67050
67537
 
67051
67538
  // src/controllers/online-forms-v2.controller.ts
67052
- import { BadRequestError as BadRequestError225, logger as logger195 } from "@7365admin1/node-server-utils";
67053
- import Joi146 from "joi";
67539
+ import { BadRequestError as BadRequestError226, logger as logger196 } from "@7365admin1/node-server-utils";
67540
+ import Joi148 from "joi";
67054
67541
  import ExcelJS3 from "exceljs";
67055
67542
  import fs6 from "fs";
67056
67543
  function useFormEntryController() {
@@ -67076,14 +67563,14 @@ function useFormEntryController() {
67076
67563
  async function uploadFormEntrys(req, res, next) {
67077
67564
  try {
67078
67565
  if (!req.file) {
67079
- next(new BadRequestError225("Excel file is required."));
67566
+ next(new BadRequestError226("Excel file is required."));
67080
67567
  return;
67081
67568
  }
67082
67569
  const workbook = new ExcelJS3.Workbook();
67083
67570
  await workbook.xlsx.readFile(req.file.path);
67084
67571
  const worksheet = workbook.worksheets[0];
67085
67572
  if (!worksheet) {
67086
- next(new BadRequestError225("No worksheet found in uploaded Excel file."));
67573
+ next(new BadRequestError226("No worksheet found in uploaded Excel file."));
67087
67574
  return;
67088
67575
  }
67089
67576
  const headerRow = worksheet.getRow(1);
@@ -67111,8 +67598,8 @@ function useFormEntryController() {
67111
67598
  });
67112
67599
  if (error) {
67113
67600
  const messages = error.details.map((d) => d.message).join(", ");
67114
- logger195.log({ level: "error", message: messages });
67115
- next(new BadRequestError225(messages));
67601
+ logger196.log({ level: "error", message: messages });
67602
+ next(new BadRequestError226(messages));
67116
67603
  return;
67117
67604
  }
67118
67605
  const result = await _add(value);
@@ -67120,25 +67607,25 @@ function useFormEntryController() {
67120
67607
  fs6.unlink(req.file.path, () => {
67121
67608
  });
67122
67609
  } catch (error) {
67123
- logger195.log({ level: "error", message: error.message });
67610
+ logger196.log({ level: "error", message: error.message });
67124
67611
  next(error);
67125
67612
  }
67126
67613
  }
67127
67614
  async function getAll(req, res, next) {
67128
67615
  try {
67129
- const schema2 = Joi146.object({
67130
- search: Joi146.string().optional().allow("", null),
67131
- page: Joi146.number().integer().min(1).allow("", null).default(1),
67132
- limit: Joi146.number().integer().min(1).max(100).allow("", null).default(10),
67133
- status: Joi146.string().optional().allow(null, ""),
67134
- org: Joi146.string().hex().optional().allow("", null),
67135
- site: Joi146.string().hex().optional().allow("", null)
67616
+ const schema2 = Joi148.object({
67617
+ search: Joi148.string().optional().allow("", null),
67618
+ page: Joi148.number().integer().min(1).allow("", null).default(1),
67619
+ limit: Joi148.number().integer().min(1).max(100).allow("", null).default(10),
67620
+ status: Joi148.string().optional().allow(null, ""),
67621
+ org: Joi148.string().hex().optional().allow("", null),
67622
+ site: Joi148.string().hex().optional().allow("", null)
67136
67623
  });
67137
67624
  const { error, value } = schema2.validate(req.query);
67138
67625
  if (error) {
67139
67626
  const messages = error.details.map((d) => d.message).join(", ");
67140
- logger195.log({ level: "error", message: messages });
67141
- next(new BadRequestError225(messages));
67627
+ logger196.log({ level: "error", message: messages });
67628
+ next(new BadRequestError226(messages));
67142
67629
  return;
67143
67630
  }
67144
67631
  const { search, page, limit, status, org, site } = value;
@@ -67146,21 +67633,21 @@ function useFormEntryController() {
67146
67633
  res.json(data);
67147
67634
  return;
67148
67635
  } catch (error) {
67149
- logger195.log({ level: "error", message: error.message });
67636
+ logger196.log({ level: "error", message: error.message });
67150
67637
  next(error);
67151
67638
  return;
67152
67639
  }
67153
67640
  }
67154
67641
  async function getFormEntryById(req, res, next) {
67155
67642
  try {
67156
- const schema2 = Joi146.object({
67157
- _id: Joi146.string().hex().length(24).required()
67643
+ const schema2 = Joi148.object({
67644
+ _id: Joi148.string().hex().length(24).required()
67158
67645
  });
67159
67646
  const { error, value } = schema2.validate({ _id: req.params.id });
67160
67647
  if (error) {
67161
67648
  const messages = error.details.map((d) => d.message).join(", ");
67162
- logger195.log({ level: "error", message: messages });
67163
- next(new BadRequestError225(messages));
67649
+ logger196.log({ level: "error", message: messages });
67650
+ next(new BadRequestError226(messages));
67164
67651
  return;
67165
67652
  }
67166
67653
  const { _id } = value;
@@ -67168,7 +67655,7 @@ function useFormEntryController() {
67168
67655
  res.json(data);
67169
67656
  return;
67170
67657
  } catch (error) {
67171
- logger195.log({ level: "error", message: error.message });
67658
+ logger196.log({ level: "error", message: error.message });
67172
67659
  next(error);
67173
67660
  return;
67174
67661
  }
@@ -67181,8 +67668,8 @@ function useFormEntryController() {
67181
67668
  });
67182
67669
  if (error) {
67183
67670
  const messages = error.details.map((d) => d.message).join(", ");
67184
- logger195.log({ level: "error", message: messages });
67185
- next(new BadRequestError225(messages));
67671
+ logger196.log({ level: "error", message: messages });
67672
+ next(new BadRequestError226(messages));
67186
67673
  return;
67187
67674
  }
67188
67675
  const { _id, ...rest } = value;
@@ -67190,26 +67677,26 @@ function useFormEntryController() {
67190
67677
  res.json({ message: "Successfully updated online form." });
67191
67678
  return;
67192
67679
  } catch (error) {
67193
- logger195.log({ level: "error", message: error.message });
67680
+ logger196.log({ level: "error", message: error.message });
67194
67681
  next(error);
67195
67682
  return;
67196
67683
  }
67197
67684
  }
67198
67685
  async function deleteFormEntryById(req, res, next) {
67199
67686
  try {
67200
- const validation = Joi146.string().hex().required();
67687
+ const validation = Joi148.string().hex().required();
67201
67688
  const _id = req.params.id;
67202
67689
  const { error } = validation.validate(_id);
67203
67690
  if (error) {
67204
- logger195.log({ level: "error", message: error.message });
67205
- next(new BadRequestError225(error.message));
67691
+ logger196.log({ level: "error", message: error.message });
67692
+ next(new BadRequestError226(error.message));
67206
67693
  return;
67207
67694
  }
67208
67695
  await _deleteOnlineFormById(_id);
67209
67696
  res.json({ message: "Successfully deleted online form." });
67210
67697
  return;
67211
67698
  } catch (error) {
67212
- logger195.log({ level: "error", message: error.message });
67699
+ logger196.log({ level: "error", message: error.message });
67213
67700
  next(error);
67214
67701
  return;
67215
67702
  }
@@ -67226,8 +67713,8 @@ function useFormEntryController() {
67226
67713
  });
67227
67714
  if (error) {
67228
67715
  const messages = error.details.map((d) => d.message).join(", ");
67229
- logger195.log({ level: "error", message: messages });
67230
- next(new BadRequestError225(messages));
67716
+ logger196.log({ level: "error", message: messages });
67717
+ next(new BadRequestError226(messages));
67231
67718
  return;
67232
67719
  }
67233
67720
  try {
@@ -67235,7 +67722,7 @@ function useFormEntryController() {
67235
67722
  res.status(201).json({ message: data });
67236
67723
  return;
67237
67724
  } catch (error2) {
67238
- logger195.log({ level: "error", message: error2.message });
67725
+ logger196.log({ level: "error", message: error2.message });
67239
67726
  next(error2);
67240
67727
  return;
67241
67728
  }
@@ -67247,8 +67734,8 @@ function useFormEntryController() {
67247
67734
  });
67248
67735
  if (error) {
67249
67736
  const messages = error.details.map((d) => d.message).join(", ");
67250
- logger195.log({ level: "error", message: messages });
67251
- next(new BadRequestError225(messages));
67737
+ logger196.log({ level: "error", message: messages });
67738
+ next(new BadRequestError226(messages));
67252
67739
  return;
67253
67740
  }
67254
67741
  try {
@@ -67256,7 +67743,7 @@ function useFormEntryController() {
67256
67743
  res.status(201).json({ message: data });
67257
67744
  return;
67258
67745
  } catch (error2) {
67259
- logger195.log({ level: "error", message: error2.message });
67746
+ logger196.log({ level: "error", message: error2.message });
67260
67747
  next(error2);
67261
67748
  return;
67262
67749
  }
@@ -67264,22 +67751,22 @@ function useFormEntryController() {
67264
67751
  async function residentForm(req, res, next) {
67265
67752
  try {
67266
67753
  const { site, userId, org } = req.query;
67267
- const residentFormPayload = Joi146.object({
67268
- org: Joi146.string().hex().required(),
67269
- site: Joi146.string().hex().required(),
67270
- userId: Joi146.string().hex().required()
67754
+ const residentFormPayload = Joi148.object({
67755
+ org: Joi148.string().hex().required(),
67756
+ site: Joi148.string().hex().required(),
67757
+ userId: Joi148.string().hex().required()
67271
67758
  });
67272
67759
  const { error } = residentFormPayload.validate({ site, userId, org }, { abortEarly: true });
67273
67760
  if (error) {
67274
67761
  const messages = error.details.map((d) => d.message).join(", ");
67275
- logger195.log({ level: "error", message: messages });
67276
- next(new BadRequestError225(messages));
67762
+ logger196.log({ level: "error", message: messages });
67763
+ next(new BadRequestError226(messages));
67277
67764
  return;
67278
67765
  }
67279
67766
  const result = await _residentForm({ userId, site, org });
67280
67767
  res.json(result);
67281
67768
  } catch (error) {
67282
- logger195.log({ level: "error", message: error.message });
67769
+ logger196.log({ level: "error", message: error.message });
67283
67770
  next(error);
67284
67771
  return;
67285
67772
  }
@@ -67297,11 +67784,11 @@ function useFormEntryController() {
67297
67784
  }
67298
67785
 
67299
67786
  // src/services/building-level.service.ts
67300
- import { useAtlas as useAtlas128 } from "@7365admin1/node-server-utils";
67787
+ import { useAtlas as useAtlas129 } from "@7365admin1/node-server-utils";
67301
67788
  function useBuildingLevelService() {
67302
67789
  const { add: _add, updateLevelById: _updateLevelById } = useBuildingLevelRepo();
67303
67790
  async function add(value) {
67304
- const session = useAtlas128.getClient()?.startSession();
67791
+ const session = useAtlas129.getClient()?.startSession();
67305
67792
  try {
67306
67793
  session?.startTransaction();
67307
67794
  await _add(value, session);
@@ -67315,7 +67802,7 @@ function useBuildingLevelService() {
67315
67802
  }
67316
67803
  }
67317
67804
  async function updateLevelById(_id, value) {
67318
- const session = useAtlas128.getClient()?.startSession();
67805
+ const session = useAtlas129.getClient()?.startSession();
67319
67806
  try {
67320
67807
  session?.startTransaction();
67321
67808
  await _updateLevelById(_id, value, session);
@@ -67335,8 +67822,8 @@ function useBuildingLevelService() {
67335
67822
  }
67336
67823
 
67337
67824
  // src/controllers/building-level.controller.ts
67338
- import { BadRequestError as BadRequestError226, logger as logger196 } from "@7365admin1/node-server-utils";
67339
- import Joi147 from "joi";
67825
+ import { BadRequestError as BadRequestError227, logger as logger197 } from "@7365admin1/node-server-utils";
67826
+ import Joi149 from "joi";
67340
67827
  function useBuildingLevelController() {
67341
67828
  const { add: _add, updateLevelById: _updateLevelById } = useBuildingLevelService();
67342
67829
  const {
@@ -67353,8 +67840,8 @@ function useBuildingLevelController() {
67353
67840
  });
67354
67841
  if (error) {
67355
67842
  const messages = error.details.map((d) => d.message).join(", ");
67356
- logger196.log({ level: "error", message: messages });
67357
- next(new BadRequestError226(messages));
67843
+ logger197.log({ level: "error", message: messages });
67844
+ next(new BadRequestError227(messages));
67358
67845
  return;
67359
67846
  }
67360
67847
  const result = await _add(value);
@@ -67365,20 +67852,20 @@ function useBuildingLevelController() {
67365
67852
  }
67366
67853
  async function getAll(req, res, next) {
67367
67854
  try {
67368
- const validation = Joi147.object({
67369
- page: Joi147.number().min(1).optional().default(1),
67370
- limit: Joi147.number().min(1).optional().default(20),
67371
- search: Joi147.string().optional().allow("", null),
67372
- site: Joi147.string().hex().length(24).optional().allow("", null),
67373
- status: Joi147.string().valid(...Object.values(BuildingLevelStatus)).default("active" /* ACTIVE */)
67855
+ const validation = Joi149.object({
67856
+ page: Joi149.number().min(1).optional().default(1),
67857
+ limit: Joi149.number().min(1).optional().default(20),
67858
+ search: Joi149.string().optional().allow("", null),
67859
+ site: Joi149.string().hex().length(24).optional().allow("", null),
67860
+ status: Joi149.string().valid(...Object.values(BuildingLevelStatus)).default("active" /* ACTIVE */)
67374
67861
  });
67375
67862
  const { error, value } = validation.validate(req.query, {
67376
67863
  abortEarly: false
67377
67864
  });
67378
67865
  if (error) {
67379
67866
  const messages = error.details.map((d) => d.message);
67380
- logger196.log({ level: "error", message: messages.join(", ") });
67381
- next(new BadRequestError226(messages.join(", ")));
67867
+ logger197.log({ level: "error", message: messages.join(", ") });
67868
+ next(new BadRequestError227(messages.join(", ")));
67382
67869
  return;
67383
67870
  }
67384
67871
  const { page, limit, status, site, search } = value;
@@ -67397,14 +67884,14 @@ function useBuildingLevelController() {
67397
67884
  }
67398
67885
  async function getById(req, res, next) {
67399
67886
  try {
67400
- const schema2 = Joi147.object({
67401
- id: Joi147.string().hex().length(24).required()
67887
+ const schema2 = Joi149.object({
67888
+ id: Joi149.string().hex().length(24).required()
67402
67889
  });
67403
67890
  const { error, value } = schema2.validate({ id: req.params.id });
67404
67891
  if (error) {
67405
67892
  const messages = error.details.map((d) => d.message);
67406
- logger196.log({ level: "error", message: messages.join(", ") });
67407
- next(new BadRequestError226(messages.join(", ")));
67893
+ logger197.log({ level: "error", message: messages.join(", ") });
67894
+ next(new BadRequestError227(messages.join(", ")));
67408
67895
  return;
67409
67896
  }
67410
67897
  const { id } = value;
@@ -67423,8 +67910,8 @@ function useBuildingLevelController() {
67423
67910
  });
67424
67911
  if (error) {
67425
67912
  const messages = error.details.map((d) => d.message);
67426
- logger196.log({ level: "error", message: messages.join(", ") });
67427
- next(new BadRequestError226(messages.join(", ")));
67913
+ logger197.log({ level: "error", message: messages.join(", ") });
67914
+ next(new BadRequestError227(messages.join(", ")));
67428
67915
  return;
67429
67916
  }
67430
67917
  const { _id, ...rest } = value;
@@ -67436,14 +67923,14 @@ function useBuildingLevelController() {
67436
67923
  }
67437
67924
  async function deleteById(req, res, next) {
67438
67925
  try {
67439
- const schema2 = Joi147.object({
67440
- id: Joi147.string().hex().required()
67926
+ const schema2 = Joi149.object({
67927
+ id: Joi149.string().hex().required()
67441
67928
  });
67442
67929
  const { error, value } = schema2.validate({ id: req.params.id });
67443
67930
  if (error) {
67444
67931
  const messages = error.details.map((d) => d.message);
67445
- logger196.log({ level: "error", message: messages.join(", ") });
67446
- next(new BadRequestError226(messages.join(", ")));
67932
+ logger197.log({ level: "error", message: messages.join(", ") });
67933
+ next(new BadRequestError227(messages.join(", ")));
67447
67934
  return;
67448
67935
  }
67449
67936
  const { id } = value;
@@ -67456,19 +67943,19 @@ function useBuildingLevelController() {
67456
67943
  }
67457
67944
  async function batchUpdateByIds(req, res, next) {
67458
67945
  try {
67459
- const schema2 = Joi147.array().items(
67460
- Joi147.object({
67461
- _id: Joi147.string().hex().length(24).required(),
67462
- value: Joi147.object({
67463
- name: Joi147.string().optional().allow("", null)
67946
+ const schema2 = Joi149.array().items(
67947
+ Joi149.object({
67948
+ _id: Joi149.string().hex().length(24).required(),
67949
+ value: Joi149.object({
67950
+ name: Joi149.string().optional().allow("", null)
67464
67951
  }).required()
67465
67952
  })
67466
67953
  );
67467
67954
  const { error, value } = schema2.validate(req.body);
67468
67955
  if (error) {
67469
67956
  const messages = error.details.map((d) => d.message);
67470
- logger196.log({ level: "error", message: messages.join(", ") });
67471
- next(new BadRequestError226(messages.join(", ")));
67957
+ logger197.log({ level: "error", message: messages.join(", ") });
67958
+ next(new BadRequestError227(messages.join(", ")));
67472
67959
  return;
67473
67960
  }
67474
67961
  const updates = value.map((item) => ({
@@ -67483,9 +67970,9 @@ function useBuildingLevelController() {
67483
67970
  }
67484
67971
  async function getBuildingLevelList(req, res, next) {
67485
67972
  try {
67486
- const schema2 = Joi147.object({
67487
- site: Joi147.string().hex().length(24).required(),
67488
- block: Joi147.string().hex().length(24).required()
67973
+ const schema2 = Joi149.object({
67974
+ site: Joi149.string().hex().length(24).required(),
67975
+ block: Joi149.string().hex().length(24).required()
67489
67976
  });
67490
67977
  const { error, value } = schema2.validate({
67491
67978
  site: req.params.siteId,
@@ -67493,8 +67980,8 @@ function useBuildingLevelController() {
67493
67980
  });
67494
67981
  if (error) {
67495
67982
  const messages = error.details.map((d) => d.message).join(", ");
67496
- logger196.log({ level: "error", message: messages });
67497
- next(new BadRequestError226(messages));
67983
+ logger197.log({ level: "error", message: messages });
67984
+ next(new BadRequestError227(messages));
67498
67985
  return;
67499
67986
  }
67500
67987
  const { site, block } = value;
@@ -67515,10 +68002,1363 @@ function useBuildingLevelController() {
67515
68002
  getBuildingLevelList
67516
68003
  };
67517
68004
  }
68005
+
68006
+ // src/models/hid-amico.model.ts
68007
+ import { BadRequestError as BadRequestError228, logger as logger198 } from "@7365admin1/node-server-utils";
68008
+ import { ObjectId as ObjectId153 } from "mongodb";
68009
+ import Joi150 from "joi";
68010
+ function canReadObjectId(value) {
68011
+ if (value instanceof ObjectId153)
68012
+ return true;
68013
+ if (typeof value === "string")
68014
+ return ObjectId153.isValid(value);
68015
+ if (value && typeof value === "object") {
68016
+ const candidate = value;
68017
+ if (canReadObjectId(candidate._id) || canReadObjectId(candidate.$oid))
68018
+ return true;
68019
+ if (typeof candidate.toHexString === "function" && ObjectId153.isValid(candidate.toHexString()))
68020
+ return true;
68021
+ if (typeof candidate.toString === "function") {
68022
+ const text = candidate.toString();
68023
+ return text !== "[object Object]" && ObjectId153.isValid(text);
68024
+ }
68025
+ }
68026
+ return false;
68027
+ }
68028
+ function toObjectId23(value, label = "ID") {
68029
+ if (value instanceof ObjectId153)
68030
+ return value;
68031
+ if (typeof value === "string" && ObjectId153.isValid(value))
68032
+ return new ObjectId153(value);
68033
+ if (value && typeof value === "object") {
68034
+ const candidate = value;
68035
+ if (candidate._id)
68036
+ return toObjectId23(candidate._id, label);
68037
+ if (candidate.$oid)
68038
+ return toObjectId23(candidate.$oid, label);
68039
+ if (typeof candidate.toHexString === "function")
68040
+ return toObjectId23(candidate.toHexString(), label);
68041
+ if (typeof candidate.toString === "function") {
68042
+ const text = candidate.toString();
68043
+ if (text !== "[object Object]")
68044
+ return toObjectId23(text, label);
68045
+ }
68046
+ }
68047
+ throw new BadRequestError228(`Invalid ${label} format`);
68048
+ }
68049
+ var objectIdSchema2 = Joi150.custom((value, helpers) => canReadObjectId(value) ? value : helpers.error("any.invalid"), "ObjectId").messages({
68050
+ "any.invalid": "{{#label}} must be a valid ObjectId"
68051
+ });
68052
+ var schemaHidAmicoReader = Joi150.object({
68053
+ _id: objectIdSchema2.optional(),
68054
+ site: objectIdSchema2.required(),
68055
+ name: Joi150.string().trim().required(),
68056
+ baseUrl: Joi150.string().uri({ scheme: ["http", "https"] }).required(),
68057
+ username: Joi150.string().trim().required(),
68058
+ password: Joi150.string().required(),
68059
+ location: Joi150.string().allow(null, "").optional(),
68060
+ deviceId: Joi150.string().allow(null, "").optional(),
68061
+ monitorPath: Joi150.string().allow(null, "").optional(),
68062
+ enabled: Joi150.boolean().optional(),
68063
+ status: Joi150.string().valid("active", "inactive", "deleted", "offline").optional(),
68064
+ lastSeenAt: Joi150.date().optional(),
68065
+ lastSyncAt: Joi150.date().optional(),
68066
+ lastSyncStatus: Joi150.string().valid("idle", "running", "completed", "failed").optional(),
68067
+ lastSyncMessage: Joi150.string().allow(null, "").optional(),
68068
+ createdAt: Joi150.date().optional(),
68069
+ updatedAt: Joi150.date().optional(),
68070
+ deletedAt: Joi150.date().optional()
68071
+ });
68072
+ var schemaUpdateHidAmicoReader = Joi150.object({
68073
+ site: objectIdSchema2.optional(),
68074
+ name: Joi150.string().trim().optional(),
68075
+ baseUrl: Joi150.string().uri({ scheme: ["http", "https"] }).optional(),
68076
+ username: Joi150.string().trim().optional(),
68077
+ password: Joi150.string().allow(null, "").optional(),
68078
+ location: Joi150.string().allow(null, "").optional(),
68079
+ deviceId: Joi150.string().allow(null, "").optional(),
68080
+ monitorPath: Joi150.string().allow(null, "").optional(),
68081
+ enabled: Joi150.boolean().optional(),
68082
+ status: Joi150.string().valid("active", "inactive", "deleted", "offline").optional(),
68083
+ lastSeenAt: Joi150.date().optional(),
68084
+ lastSyncAt: Joi150.date().optional(),
68085
+ lastSyncStatus: Joi150.string().valid("idle", "running", "completed", "failed").optional(),
68086
+ lastSyncMessage: Joi150.string().allow(null, "").optional(),
68087
+ deletedAt: Joi150.date().optional()
68088
+ });
68089
+ var schemaHidAmicoEvent = Joi150.object({
68090
+ _id: objectIdSchema2.optional(),
68091
+ reader: objectIdSchema2.required(),
68092
+ site: objectIdSchema2.optional(),
68093
+ type: Joi150.string().required(),
68094
+ payload: Joi150.object().unknown(true).required(),
68095
+ status: Joi150.string().valid("received", "processed", "failed").optional(),
68096
+ createdAt: Joi150.date().optional()
68097
+ });
68098
+ var schemaHidAmicoIdentity = Joi150.object({
68099
+ _id: objectIdSchema2.optional(),
68100
+ reader: objectIdSchema2.required(),
68101
+ site: objectIdSchema2.required(),
68102
+ hidUserId: Joi150.alternatives(Joi150.string(), Joi150.number()).optional().allow(null, ""),
68103
+ registration: Joi150.string().optional().allow(null, ""),
68104
+ cardNo: Joi150.string().optional().allow(null, ""),
68105
+ person: objectIdSchema2.optional().allow(null, ""),
68106
+ user: objectIdSchema2.optional().allow(null, ""),
68107
+ member: objectIdSchema2.optional().allow(null, ""),
68108
+ visitor: objectIdSchema2.optional().allow(null, ""),
68109
+ type: Joi150.string().valid("resident", "staff", "contractor", "visitor", "admin", "unknown").required(),
68110
+ status: Joi150.string().valid("active", "inactive", "deleted").optional(),
68111
+ metadata: Joi150.object().unknown(true).optional(),
68112
+ createdAt: Joi150.date().optional(),
68113
+ updatedAt: Joi150.date().optional(),
68114
+ deletedAt: Joi150.date().optional()
68115
+ }).or("hidUserId", "registration", "cardNo");
68116
+ var schemaCreateHidAmicoIdentity = Joi150.object({
68117
+ site: objectIdSchema2.optional(),
68118
+ hidUserId: Joi150.alternatives(Joi150.string(), Joi150.number()).optional().allow(null, ""),
68119
+ registration: Joi150.string().optional().allow(null, ""),
68120
+ cardNo: Joi150.string().optional().allow(null, ""),
68121
+ person: objectIdSchema2.optional().allow(null, ""),
68122
+ user: objectIdSchema2.optional().allow(null, ""),
68123
+ member: objectIdSchema2.optional().allow(null, ""),
68124
+ visitor: objectIdSchema2.optional().allow(null, ""),
68125
+ type: Joi150.string().valid("resident", "staff", "contractor", "visitor", "admin", "unknown").required(),
68126
+ status: Joi150.string().valid("active", "inactive", "deleted").optional(),
68127
+ metadata: Joi150.object().unknown(true).optional()
68128
+ }).or("hidUserId", "registration", "cardNo");
68129
+ var schemaUpdateHidAmicoIdentity = Joi150.object({
68130
+ hidUserId: Joi150.alternatives(Joi150.string(), Joi150.number()).optional().allow(null, ""),
68131
+ registration: Joi150.string().optional().allow(null, ""),
68132
+ cardNo: Joi150.string().optional().allow(null, ""),
68133
+ person: objectIdSchema2.optional().allow(null, ""),
68134
+ user: objectIdSchema2.optional().allow(null, ""),
68135
+ member: objectIdSchema2.optional().allow(null, ""),
68136
+ visitor: objectIdSchema2.optional().allow(null, ""),
68137
+ type: Joi150.string().valid("resident", "staff", "contractor", "visitor", "admin", "unknown").optional(),
68138
+ status: Joi150.string().valid("active", "inactive", "deleted").optional(),
68139
+ metadata: Joi150.object().unknown(true).optional(),
68140
+ deletedAt: Joi150.date().optional()
68141
+ });
68142
+ var schemaHidAmicoReaderIdParams = Joi150.object({
68143
+ readerId: Joi150.string().hex().length(24).required()
68144
+ });
68145
+ var schemaHidAmicoUserImageParams = Joi150.object({
68146
+ readerId: Joi150.string().hex().length(24).required(),
68147
+ hidUserId: Joi150.alternatives().try(Joi150.string(), Joi150.number()).required()
68148
+ });
68149
+ var schemaHidAmicoIdentityIdParams = Joi150.object({
68150
+ identityId: Joi150.string().hex().length(24).required()
68151
+ });
68152
+ var schemaHidAmicoReaderListQuery = Joi150.object({
68153
+ site: Joi150.string().hex().length(24).optional(),
68154
+ page: Joi150.number().min(1).optional(),
68155
+ limit: Joi150.number().min(1).optional()
68156
+ });
68157
+ var schemaHidAmicoLogQuery = Joi150.object({
68158
+ page: Joi150.number().min(1).optional(),
68159
+ limit: Joi150.number().min(1).optional(),
68160
+ type: Joi150.string().optional()
68161
+ });
68162
+ var schemaHidAmicoIdentityQuery = Joi150.object({
68163
+ page: Joi150.number().min(1).optional(),
68164
+ limit: Joi150.number().min(1).optional(),
68165
+ type: Joi150.string().valid("resident", "staff", "contractor", "visitor", "admin", "unknown").optional(),
68166
+ status: Joi150.string().valid("active", "inactive", "deleted").optional(),
68167
+ search: Joi150.string().allow("").optional()
68168
+ });
68169
+ var schemaHidAmicoSync = Joi150.object({
68170
+ objects: Joi150.array().items(
68171
+ Joi150.object({
68172
+ object: Joi150.string().required(),
68173
+ values: Joi150.array().items(Joi150.object().unknown(true)).required()
68174
+ }).unknown(true)
68175
+ ).optional(),
68176
+ users: Joi150.array().items(Joi150.object().unknown(true)).optional(),
68177
+ cards: Joi150.array().items(Joi150.object().unknown(true)).optional(),
68178
+ qrcodes: Joi150.array().items(Joi150.object().unknown(true)).optional(),
68179
+ pins: Joi150.array().items(Joi150.object().unknown(true)).optional()
68180
+ }).unknown(true);
68181
+ var schemaHidAmicoExecuteActions = Joi150.object({
68182
+ actions: Joi150.array().items(Joi150.object().unknown(true)).min(1).required()
68183
+ }).unknown(true);
68184
+ var schemaHidAmicoConfiguration = Joi150.object().pattern(Joi150.string(), Joi150.array().items(Joi150.string())).min(1).unknown(true);
68185
+ var schemaHidAmicoSetConfiguration = Joi150.object().unknown(true);
68186
+ var schemaHidAmicoObjectOperation = Joi150.object({
68187
+ operation: Joi150.string().valid("load", "create", "modify", "destroy").required(),
68188
+ object: Joi150.string().required(),
68189
+ values: Joi150.alternatives().try(
68190
+ Joi150.array().items(Joi150.object().unknown(true)),
68191
+ Joi150.object().unknown(true)
68192
+ ).optional(),
68193
+ where: Joi150.object().unknown(true).optional(),
68194
+ fields: Joi150.array().items(Joi150.string()).optional(),
68195
+ order: Joi150.array().items(Joi150.string()).optional(),
68196
+ limit: Joi150.number().integer().min(1).optional(),
68197
+ offset: Joi150.number().integer().min(0).optional()
68198
+ }).unknown(true);
68199
+ var schemaHidAmicoNotificationParams = Joi150.object({
68200
+ readerId: Joi150.string().hex().length(24).required(),
68201
+ type: Joi150.string().valid(
68202
+ "dao",
68203
+ "template",
68204
+ "user_image",
68205
+ "card",
68206
+ "pin",
68207
+ "password",
68208
+ "operation_mode",
68209
+ "door",
68210
+ "secbox",
68211
+ "access_photo",
68212
+ "new_user_identified",
68213
+ "push_result"
68214
+ ).required()
68215
+ });
68216
+ function MHidAmicoReader(value) {
68217
+ const { error } = schemaHidAmicoReader.validate(value);
68218
+ if (error) {
68219
+ logger198.info(`HID Amico reader: ${error.message}`);
68220
+ throw new BadRequestError228(error.message);
68221
+ }
68222
+ return {
68223
+ _id: value._id ? toObjectId23(value._id, "reader ID") : new ObjectId153(),
68224
+ site: toObjectId23(value.site, "site ID"),
68225
+ name: value.name,
68226
+ baseUrl: value.baseUrl.replace(/\/+$/, ""),
68227
+ username: value.username,
68228
+ password: value.password,
68229
+ location: value.location ?? "",
68230
+ deviceId: value.deviceId ?? "",
68231
+ monitorPath: value.monitorPath ?? "api/notifications",
68232
+ enabled: value.enabled ?? true,
68233
+ status: value.status ?? "active",
68234
+ lastSeenAt: value.lastSeenAt ?? "",
68235
+ lastSyncAt: value.lastSyncAt ?? "",
68236
+ lastSyncStatus: value.lastSyncStatus ?? "idle",
68237
+ lastSyncMessage: value.lastSyncMessage ?? "",
68238
+ createdAt: value.createdAt ?? /* @__PURE__ */ new Date(),
68239
+ updatedAt: value.updatedAt ?? /* @__PURE__ */ new Date(),
68240
+ deletedAt: value.deletedAt ?? ""
68241
+ };
68242
+ }
68243
+ function MHidAmicoEvent(value) {
68244
+ const { error } = schemaHidAmicoEvent.validate(value);
68245
+ if (error) {
68246
+ logger198.info(`HID Amico event: ${error.message}`);
68247
+ throw new BadRequestError228(error.message);
68248
+ }
68249
+ return {
68250
+ _id: value._id ? toObjectId23(value._id, "event ID") : new ObjectId153(),
68251
+ reader: toObjectId23(value.reader, "reader ID"),
68252
+ site: value.site ? toObjectId23(value.site, "site ID") : void 0,
68253
+ type: value.type,
68254
+ payload: value.payload,
68255
+ status: value.status ?? "received",
68256
+ createdAt: value.createdAt ?? /* @__PURE__ */ new Date()
68257
+ };
68258
+ }
68259
+ function optionalObjectId(value) {
68260
+ return value ? toObjectId23(value) : void 0;
68261
+ }
68262
+ function MHidAmicoIdentity(value) {
68263
+ const { error } = schemaHidAmicoIdentity.validate(value);
68264
+ if (error) {
68265
+ logger198.info(`HID Amico identity: ${error.message}`);
68266
+ throw new BadRequestError228(error.message);
68267
+ }
68268
+ return {
68269
+ _id: value._id ? toObjectId23(value._id, "identity ID") : new ObjectId153(),
68270
+ reader: toObjectId23(value.reader, "reader ID"),
68271
+ site: toObjectId23(value.site, "site ID"),
68272
+ hidUserId: value.hidUserId === void 0 || value.hidUserId === null ? "" : String(value.hidUserId),
68273
+ registration: value.registration ?? "",
68274
+ cardNo: value.cardNo ?? "",
68275
+ person: optionalObjectId(value.person),
68276
+ user: optionalObjectId(value.user),
68277
+ member: optionalObjectId(value.member),
68278
+ visitor: optionalObjectId(value.visitor),
68279
+ type: value.type,
68280
+ status: value.status ?? "active",
68281
+ metadata: value.metadata ?? {},
68282
+ createdAt: value.createdAt ?? /* @__PURE__ */ new Date(),
68283
+ updatedAt: value.updatedAt ?? /* @__PURE__ */ new Date(),
68284
+ deletedAt: value.deletedAt ?? ""
68285
+ };
68286
+ }
68287
+
68288
+ // src/repositories/hid-amico.repo.ts
68289
+ import {
68290
+ BadRequestError as BadRequestError229,
68291
+ InternalServerError as InternalServerError84,
68292
+ logger as logger199,
68293
+ paginate as paginate65,
68294
+ useAtlas as useAtlas130
68295
+ } from "@7365admin1/node-server-utils";
68296
+ import { ObjectId as ObjectId154 } from "mongodb";
68297
+ function useHidAmicoRepo() {
68298
+ function db() {
68299
+ const instance = useAtlas130.getDb();
68300
+ if (!instance) {
68301
+ throw new InternalServerError84("Unable to connect to server.");
68302
+ }
68303
+ return instance;
68304
+ }
68305
+ function readers() {
68306
+ return db().collection("hid-amico-readers");
68307
+ }
68308
+ function events() {
68309
+ return db().collection("hid-amico-events");
68310
+ }
68311
+ function identities() {
68312
+ return db().collection("hid-amico-identities");
68313
+ }
68314
+ function toId(id, label = "ID") {
68315
+ try {
68316
+ return new ObjectId154(id);
68317
+ } catch {
68318
+ throw new BadRequestError229(`Invalid ${label} format`);
68319
+ }
68320
+ }
68321
+ function hideSecret(reader) {
68322
+ if (!reader) {
68323
+ return reader;
68324
+ }
68325
+ const { password, ...safeReader } = reader;
68326
+ const status = safeReader.lastSyncStatus === "failed" && safeReader.status === "active" ? "offline" : safeReader.status;
68327
+ return {
68328
+ ...safeReader,
68329
+ status,
68330
+ passwordSet: Boolean(password)
68331
+ };
68332
+ }
68333
+ function escapeRegex(value) {
68334
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
68335
+ }
68336
+ function buildIdentityKeyQuery(value) {
68337
+ const or = [];
68338
+ if (value.hidUserId !== void 0 && value.hidUserId !== null && String(value.hidUserId) !== "") {
68339
+ or.push({ hidUserId: String(value.hidUserId) });
68340
+ }
68341
+ if (value.registration) {
68342
+ or.push({ registration: value.registration });
68343
+ }
68344
+ if (value.cardNo) {
68345
+ or.push({ cardNo: value.cardNo });
68346
+ }
68347
+ return or;
68348
+ }
68349
+ async function createIndexes() {
68350
+ try {
68351
+ await Promise.all([
68352
+ readers().createIndex({ site: 1, status: 1 }),
68353
+ readers().createIndex(
68354
+ { site: 1, baseUrl: 1 },
68355
+ { unique: true, partialFilterExpression: { status: "active" } }
68356
+ ),
68357
+ readers().createIndex({ deviceId: 1 }),
68358
+ events().createIndex({ reader: 1, createdAt: -1 }),
68359
+ events().createIndex({ site: 1, createdAt: -1 }),
68360
+ events().createIndex({ type: 1, createdAt: -1 }),
68361
+ identities().createIndex({ reader: 1, status: 1 }),
68362
+ identities().createIndex({ site: 1, status: 1 }),
68363
+ identities().createIndex({ reader: 1, hidUserId: 1 }),
68364
+ identities().createIndex({ reader: 1, registration: 1 }),
68365
+ identities().createIndex({ reader: 1, cardNo: 1 })
68366
+ ]);
68367
+ return "HID Amico indexes created.";
68368
+ } catch (error) {
68369
+ logger199.error(error.message);
68370
+ throw new Error("Failed to create HID Amico indexes.");
68371
+ }
68372
+ }
68373
+ async function add(value, session) {
68374
+ try {
68375
+ const doc = MHidAmicoReader(value);
68376
+ await readers().insertOne(doc, { session });
68377
+ return hideSecret(doc);
68378
+ } catch (error) {
68379
+ if (error.message?.includes("duplicate")) {
68380
+ throw new BadRequestError229("HID Amico reader already exists for this site and URL.");
68381
+ }
68382
+ throw error;
68383
+ }
68384
+ }
68385
+ async function list(value) {
68386
+ const page = value.page ? value.page - 1 : 0;
68387
+ const limit = value.limit || 10;
68388
+ const query = { status: { $ne: "deleted" } };
68389
+ if (value.site) {
68390
+ query.site = toId(value.site, "site ID");
68391
+ }
68392
+ const items = await readers().find(query).sort({ createdAt: -1 }).skip(page * limit).limit(limit).toArray();
68393
+ const total = await readers().countDocuments(query);
68394
+ return paginate65(items.map(hideSecret), page, limit, total);
68395
+ }
68396
+ async function getById(id, options = {}) {
68397
+ const _id = toId(id, "reader ID");
68398
+ const reader = await readers().findOne(
68399
+ { _id, status: { $ne: "deleted" } }
68400
+ );
68401
+ if (!reader) {
68402
+ throw new BadRequestError229("HID Amico reader not found.");
68403
+ }
68404
+ return options.includePassword ? reader : hideSecret(reader);
68405
+ }
68406
+ async function updateById(id, value, session) {
68407
+ const { error } = schemaUpdateHidAmicoReader.validate(value);
68408
+ if (error) {
68409
+ throw new BadRequestError229(error.message);
68410
+ }
68411
+ const _id = toId(id, "reader ID");
68412
+ const payload = {
68413
+ ...value,
68414
+ updatedAt: /* @__PURE__ */ new Date()
68415
+ };
68416
+ if (payload.site) {
68417
+ payload.site = toId(payload.site, "site ID");
68418
+ }
68419
+ if (payload.baseUrl) {
68420
+ payload.baseUrl = payload.baseUrl.replace(/\/+$/, "");
68421
+ }
68422
+ const updated = await readers().findOneAndUpdate(
68423
+ { _id, status: { $ne: "deleted" } },
68424
+ { $set: payload },
68425
+ { returnDocument: "after", session }
68426
+ );
68427
+ if (!updated) {
68428
+ throw new BadRequestError229("HID Amico reader not found.");
68429
+ }
68430
+ return hideSecret(updated);
68431
+ }
68432
+ async function markDeleted(id, session) {
68433
+ return updateById(
68434
+ id,
68435
+ {
68436
+ status: "deleted",
68437
+ enabled: false,
68438
+ deletedAt: /* @__PURE__ */ new Date()
68439
+ },
68440
+ session
68441
+ );
68442
+ }
68443
+ async function addEvent(value, session) {
68444
+ const event = MHidAmicoEvent(value);
68445
+ await events().insertOne(event, { session });
68446
+ return event;
68447
+ }
68448
+ async function listEvents(value) {
68449
+ const page = value.page ? value.page - 1 : 0;
68450
+ const limit = value.limit || 20;
68451
+ const query = { reader: toId(value.reader, "reader ID") };
68452
+ if (value.type) {
68453
+ query.type = value.type;
68454
+ }
68455
+ const items = await events().find(query).sort({ createdAt: -1 }).skip(page * limit).limit(limit).toArray();
68456
+ const total = await events().countDocuments(query);
68457
+ return paginate65(items, page, limit, total);
68458
+ }
68459
+ async function addIdentity(value, session) {
68460
+ try {
68461
+ const identity = MHidAmicoIdentity(value);
68462
+ const existing = await findExistingIdentity({
68463
+ reader: identity.reader,
68464
+ hidUserId: identity.hidUserId,
68465
+ registration: identity.registration,
68466
+ cardNo: identity.cardNo
68467
+ });
68468
+ if (existing) {
68469
+ throw new BadRequestError229("HID Amico identity already exists for this reader.");
68470
+ }
68471
+ await identities().insertOne(identity, { session });
68472
+ return identity;
68473
+ } catch (error) {
68474
+ if (error instanceof BadRequestError229) {
68475
+ throw error;
68476
+ }
68477
+ if (error.message?.includes("duplicate")) {
68478
+ throw new BadRequestError229("HID Amico identity already exists for this reader.");
68479
+ }
68480
+ throw error;
68481
+ }
68482
+ }
68483
+ async function listIdentities(value) {
68484
+ const page = value.page ? value.page - 1 : 0;
68485
+ const limit = value.limit || 20;
68486
+ const query = {
68487
+ reader: toId(value.reader, "reader ID"),
68488
+ status: value.status || { $ne: "deleted" }
68489
+ };
68490
+ if (value.type) {
68491
+ query.type = value.type;
68492
+ }
68493
+ if (value.search) {
68494
+ const search = escapeRegex(value.search);
68495
+ query.$or = [
68496
+ { hidUserId: { $regex: search, $options: "i" } },
68497
+ { registration: { $regex: search, $options: "i" } },
68498
+ { cardNo: { $regex: search, $options: "i" } }
68499
+ ];
68500
+ }
68501
+ const items = await identities().find(query).sort({ createdAt: -1 }).skip(page * limit).limit(limit).toArray();
68502
+ const total = await identities().countDocuments(query);
68503
+ return paginate65(items, page, limit, total);
68504
+ }
68505
+ async function updateIdentity(id, value, session) {
68506
+ const { error } = schemaUpdateHidAmicoIdentity.validate(value);
68507
+ if (error) {
68508
+ throw new BadRequestError229(error.message);
68509
+ }
68510
+ const payload = {
68511
+ ...value,
68512
+ updatedAt: /* @__PURE__ */ new Date()
68513
+ };
68514
+ const unsetPayload = {};
68515
+ ["person", "user", "member", "visitor"].forEach((field) => {
68516
+ if (payload[field]) {
68517
+ payload[field] = toId(payload[field], `${field} ID`);
68518
+ }
68519
+ if (payload[field] === "" || payload[field] === null) {
68520
+ delete payload[field];
68521
+ unsetPayload[field] = "";
68522
+ }
68523
+ });
68524
+ if (payload.hidUserId !== void 0 && payload.hidUserId !== null) {
68525
+ payload.hidUserId = String(payload.hidUserId);
68526
+ }
68527
+ const updated = await identities().findOneAndUpdate(
68528
+ { _id: toId(id, "identity ID"), status: { $ne: "deleted" } },
68529
+ {
68530
+ $set: payload,
68531
+ ...Object.keys(unsetPayload).length ? { $unset: unsetPayload } : {}
68532
+ },
68533
+ { returnDocument: "after", session }
68534
+ );
68535
+ if (!updated) {
68536
+ throw new BadRequestError229("HID Amico identity not found.");
68537
+ }
68538
+ return updated;
68539
+ }
68540
+ async function deleteIdentity(id, session) {
68541
+ return updateIdentity(
68542
+ id,
68543
+ {
68544
+ status: "deleted",
68545
+ deletedAt: /* @__PURE__ */ new Date()
68546
+ },
68547
+ session
68548
+ );
68549
+ }
68550
+ async function findIdentity(value) {
68551
+ const or = buildIdentityKeyQuery(value);
68552
+ if (!or.length) {
68553
+ return null;
68554
+ }
68555
+ return identities().findOne({
68556
+ reader: toId(value.reader, "reader ID"),
68557
+ status: "active",
68558
+ $or: or
68559
+ });
68560
+ }
68561
+ async function findExistingIdentity(value) {
68562
+ const or = buildIdentityKeyQuery(value);
68563
+ if (!or.length) {
68564
+ return null;
68565
+ }
68566
+ return identities().findOne({
68567
+ reader: toId(value.reader, "reader ID"),
68568
+ status: { $ne: "deleted" },
68569
+ $or: or
68570
+ });
68571
+ }
68572
+ return {
68573
+ createIndexes,
68574
+ add,
68575
+ list,
68576
+ getById,
68577
+ updateById,
68578
+ markDeleted,
68579
+ addEvent,
68580
+ listEvents,
68581
+ addIdentity,
68582
+ listIdentities,
68583
+ updateIdentity,
68584
+ deleteIdentity,
68585
+ findIdentity,
68586
+ findExistingIdentity
68587
+ };
68588
+ }
68589
+
68590
+ // src/services/hid-amico.service.ts
68591
+ import crypto5 from "crypto";
68592
+ import axios4 from "axios";
68593
+ import { BadRequestError as BadRequestError230 } from "@7365admin1/node-server-utils";
68594
+ var PASSWORD_PREFIX = "v1";
68595
+ function getSecretKey() {
68596
+ const secret = process.env.HID_AMICO_SECRET || process.env.ACCESS_TOKEN_SECRET || "iservice365-hid-amico";
68597
+ return crypto5.createHash("sha256").update(secret).digest();
68598
+ }
68599
+ function encryptSecret(value) {
68600
+ const iv = crypto5.randomBytes(12);
68601
+ const cipher = crypto5.createCipheriv("aes-256-gcm", getSecretKey(), iv);
68602
+ const encrypted = Buffer.concat([cipher.update(value, "utf8"), cipher.final()]);
68603
+ const tag = cipher.getAuthTag();
68604
+ return [PASSWORD_PREFIX, iv.toString("hex"), tag.toString("hex"), encrypted.toString("hex")].join(":");
68605
+ }
68606
+ function decryptSecret(value) {
68607
+ if (!value?.startsWith(`${PASSWORD_PREFIX}:`)) {
68608
+ return value;
68609
+ }
68610
+ const [, ivHex, tagHex, encryptedHex] = value.split(":");
68611
+ const decipher = crypto5.createDecipheriv("aes-256-gcm", getSecretKey(), Buffer.from(ivHex, "hex"));
68612
+ decipher.setAuthTag(Buffer.from(tagHex, "hex"));
68613
+ return Buffer.concat([
68614
+ decipher.update(Buffer.from(encryptedHex, "hex")),
68615
+ decipher.final()
68616
+ ]).toString("utf8");
68617
+ }
68618
+ function formatHidResponse(data) {
68619
+ if (data === void 0 || data === null) {
68620
+ return "";
68621
+ }
68622
+ const text = typeof data === "string" ? data : JSON.stringify(data);
68623
+ return text.length > 300 ? `${text.slice(0, 300)}...` : text;
68624
+ }
68625
+ function sanitizeHidPath(path5) {
68626
+ return path5.replace(/([?&]session=)[^&]+/i, "$1<redacted>");
68627
+ }
68628
+ function toHidRequestError(error, path5) {
68629
+ if (axios4.isAxiosError(error)) {
68630
+ const status = error.response?.status;
68631
+ const payload = formatHidResponse(error.response?.data);
68632
+ const detail = [
68633
+ `HID Amico request failed: ${sanitizeHidPath(path5)}`,
68634
+ status ? `status ${status}` : "",
68635
+ payload ? `response ${payload}` : error.message
68636
+ ].filter(Boolean).join(" - ");
68637
+ return new BadRequestError230(detail);
68638
+ }
68639
+ return error;
68640
+ }
68641
+ var HidAmicoClient = class {
68642
+ constructor(reader) {
68643
+ this.reader = reader;
68644
+ this.session = "";
68645
+ this.http = axios4.create({
68646
+ baseURL: reader.baseUrl.replace(/\/+$/, ""),
68647
+ timeout: 15e3,
68648
+ headers: { "Content-Type": "application/json" }
68649
+ });
68650
+ }
68651
+ async post(path5, body) {
68652
+ try {
68653
+ return await this.http.post(path5, body);
68654
+ } catch (error) {
68655
+ throw toHidRequestError(error, path5);
68656
+ }
68657
+ }
68658
+ async get(path5, responseType = "json") {
68659
+ try {
68660
+ return await this.http.get(path5, { responseType });
68661
+ } catch (error) {
68662
+ throw toHidRequestError(error, path5);
68663
+ }
68664
+ }
68665
+ url(path5) {
68666
+ const normalizedPath = path5.startsWith("/") ? path5 : `/${path5}`;
68667
+ if (!this.session) {
68668
+ return normalizedPath;
68669
+ }
68670
+ const separator = normalizedPath.includes("?") ? "&" : "?";
68671
+ return `${normalizedPath}${separator}session=${encodeURIComponent(this.session)}`;
68672
+ }
68673
+ async login() {
68674
+ const res = await this.post("/hidlogin.fcgi", {
68675
+ login: this.reader.username,
68676
+ password: decryptSecret(this.reader.password)
68677
+ });
68678
+ if (!res.data?.session) {
68679
+ throw new BadRequestError230("HID Amico login failed: missing session.");
68680
+ }
68681
+ this.session = res.data.session;
68682
+ return this.session;
68683
+ }
68684
+ async sessionIsValid() {
68685
+ if (!this.session) {
68686
+ await this.login();
68687
+ }
68688
+ const res = await this.post(this.url("/session_is_valid.fcgi"), {});
68689
+ return Boolean(res.data?.session_is_valid ?? res.data?.valid ?? true);
68690
+ }
68691
+ async getUserImage(hidUserId) {
68692
+ if (!this.session) {
68693
+ await this.login();
68694
+ }
68695
+ const path5 = this.url(`/user_get_image.fcgi?user_id=${encodeURIComponent(String(hidUserId))}`);
68696
+ const res = await this.get(path5, "arraybuffer");
68697
+ const contentType = String(res.headers?.["content-type"] || "");
68698
+ const buffer = Buffer.from(res.data);
68699
+ if (contentType.includes("application/json")) {
68700
+ const payload = JSON.parse(buffer.toString("utf8"));
68701
+ const image = payload.image || payload.photo || payload.data?.image || payload.data?.photo;
68702
+ if (!image) {
68703
+ throw new BadRequestError230("HID Amico user image response did not include an image.");
68704
+ }
68705
+ return {
68706
+ contentType: payload.contentType || payload.mimeType || "image/jpeg",
68707
+ base64: String(image).replace(/^data:image\/[a-zA-Z0-9.+-]+;base64,/, "")
68708
+ };
68709
+ }
68710
+ return {
68711
+ contentType: contentType || "image/jpeg",
68712
+ base64: buffer.toString("base64")
68713
+ };
68714
+ }
68715
+ async logout() {
68716
+ if (!this.session) {
68717
+ return;
68718
+ }
68719
+ const logoutUrl = this.url("/logout.fcgi");
68720
+ try {
68721
+ this.session = "";
68722
+ await this.post(logoutUrl, {});
68723
+ } catch {
68724
+ this.session = "";
68725
+ }
68726
+ }
68727
+ async createObjects(batch) {
68728
+ if (!this.session) {
68729
+ await this.login();
68730
+ }
68731
+ const res = await this.post(this.url("/create_objects.fcgi"), {
68732
+ object: batch.object,
68733
+ values: batch.values
68734
+ });
68735
+ return res.data;
68736
+ }
68737
+ async loadObjects(query) {
68738
+ if (!this.session) {
68739
+ await this.login();
68740
+ }
68741
+ const res = await this.post(this.url("/load_objects.fcgi"), query);
68742
+ return res.data;
68743
+ }
68744
+ async modifyObjects(payload) {
68745
+ if (!this.session) {
68746
+ await this.login();
68747
+ }
68748
+ const res = await this.post(this.url("/modify_objects.fcgi"), payload);
68749
+ return res.data;
68750
+ }
68751
+ async destroyObjects(payload) {
68752
+ if (!this.session) {
68753
+ await this.login();
68754
+ }
68755
+ const res = await this.post(this.url("/destroy_objects.fcgi"), payload);
68756
+ return res.data;
68757
+ }
68758
+ async doorState() {
68759
+ if (!this.session) {
68760
+ await this.login();
68761
+ }
68762
+ const res = await this.post(this.url("/door_state.fcgi"), {});
68763
+ return res.data;
68764
+ }
68765
+ async executeActions(actions) {
68766
+ if (!this.session) {
68767
+ await this.login();
68768
+ }
68769
+ const res = await this.post(this.url("/execute_actions.fcgi"), { actions });
68770
+ return res.data;
68771
+ }
68772
+ async getConfiguration(payload) {
68773
+ if (!this.session) {
68774
+ await this.login();
68775
+ }
68776
+ const res = await this.post(this.url("/get_configuration.fcgi"), payload);
68777
+ return res.data;
68778
+ }
68779
+ async setConfiguration(payload) {
68780
+ if (!this.session) {
68781
+ await this.login();
68782
+ }
68783
+ const res = await this.post(this.url("/set_configuration.fcgi"), payload);
68784
+ return res.data;
68785
+ }
68786
+ };
68787
+ function normalizeBatches(payload) {
68788
+ if (Array.isArray(payload?.objects)) {
68789
+ return payload.objects.filter((batch) => batch?.object && Array.isArray(batch?.values));
68790
+ }
68791
+ const batches = [];
68792
+ const mappings = [
68793
+ ["users", "users"],
68794
+ ["cards", "cards"],
68795
+ ["qrcodes", "qrcodes"],
68796
+ ["pins", "pins"]
68797
+ ];
68798
+ mappings.forEach(([key, object]) => {
68799
+ if (Array.isArray(payload?.[key]) && payload[key].length) {
68800
+ batches.push({ object, values: payload[key] });
68801
+ }
68802
+ });
68803
+ return batches;
68804
+ }
68805
+ function firstValue(payload, keys) {
68806
+ for (const key of keys) {
68807
+ const value = payload?.[key];
68808
+ if (value !== void 0 && value !== null && value !== "") {
68809
+ return value;
68810
+ }
68811
+ }
68812
+ return void 0;
68813
+ }
68814
+ function extractIdentityKeys(payload) {
68815
+ const nested = payload?.user || payload?.person || payload?.data || {};
68816
+ const merged = { ...payload, ...nested };
68817
+ return {
68818
+ hidUserId: firstValue(merged, ["hidUserId", "hid_user_id", "user_id", "userId", "id", "user"]),
68819
+ registration: firstValue(merged, ["registration", "register", "employeeNo", "staffNo", "memberNo"]),
68820
+ cardNo: firstValue(merged, ["cardNo", "card_no", "card", "cardNumber", "value"])
68821
+ };
68822
+ }
68823
+ function useHidAmicoService() {
68824
+ const repo = useHidAmicoRepo();
68825
+ async function getActiveReader(id) {
68826
+ const reader = await repo.getById(id, { includePassword: true });
68827
+ if (reader.enabled === false || reader.status === "inactive" || reader.status === "deleted") {
68828
+ throw new BadRequestError230("HID Amico reader is not active.");
68829
+ }
68830
+ return reader;
68831
+ }
68832
+ async function createReader(value) {
68833
+ return repo.add({
68834
+ ...value,
68835
+ baseUrl: value.baseUrl.replace(/\/+$/, ""),
68836
+ password: encryptSecret(value.password)
68837
+ });
68838
+ }
68839
+ async function updateReader(id, value) {
68840
+ const payload = { ...value };
68841
+ if (payload.password) {
68842
+ payload.password = encryptSecret(payload.password);
68843
+ } else {
68844
+ delete payload.password;
68845
+ }
68846
+ return repo.updateById(id, payload);
68847
+ }
68848
+ async function listReaders(value) {
68849
+ return repo.list(value);
68850
+ }
68851
+ async function deleteReader(id) {
68852
+ return repo.markDeleted(id);
68853
+ }
68854
+ async function testReader(id) {
68855
+ const reader = await repo.getById(id, { includePassword: true });
68856
+ const client = new HidAmicoClient(reader);
68857
+ try {
68858
+ await client.login();
68859
+ const valid = await client.sessionIsValid();
68860
+ await repo.updateById(id, { lastSeenAt: /* @__PURE__ */ new Date(), lastSyncMessage: "Connection test succeeded." });
68861
+ await repo.addEvent({ reader: id, site: reader.site, type: "test", payload: { valid } });
68862
+ return { valid, message: "HID Amico connection test succeeded." };
68863
+ } catch (error) {
68864
+ await repo.updateById(id, {
68865
+ status: "offline",
68866
+ lastSyncAt: /* @__PURE__ */ new Date(),
68867
+ lastSyncStatus: "failed",
68868
+ lastSyncMessage: error.message
68869
+ });
68870
+ await repo.addEvent({ reader: id, site: reader.site, type: "test_failed", payload: { message: error.message } });
68871
+ throw error;
68872
+ } finally {
68873
+ await client.logout();
68874
+ }
68875
+ }
68876
+ async function syncReader(id, payload) {
68877
+ const reader = await getActiveReader(id);
68878
+ const batches = normalizeBatches(payload);
68879
+ const client = new HidAmicoClient(reader);
68880
+ const results = [];
68881
+ await repo.updateById(id, { lastSyncStatus: "running", lastSyncMessage: "Sync started." });
68882
+ try {
68883
+ await client.login();
68884
+ for (const batch of batches) {
68885
+ const result = await client.createObjects(batch);
68886
+ results.push({ object: batch.object, count: batch.values.length, result });
68887
+ }
68888
+ const message = batches.length ? `Synced ${batches.length} HID object batch(es).` : "HID reader session verified. No sync payload was supplied.";
68889
+ await repo.updateById(id, {
68890
+ lastSeenAt: /* @__PURE__ */ new Date(),
68891
+ lastSyncAt: /* @__PURE__ */ new Date(),
68892
+ lastSyncStatus: "completed",
68893
+ lastSyncMessage: message
68894
+ });
68895
+ await repo.addEvent({ reader: id, site: reader.site, type: "sync", payload: { message, results } });
68896
+ return { message, results };
68897
+ } catch (error) {
68898
+ await repo.updateById(id, {
68899
+ status: "offline",
68900
+ lastSyncAt: /* @__PURE__ */ new Date(),
68901
+ lastSyncStatus: "failed",
68902
+ lastSyncMessage: error.message
68903
+ });
68904
+ await repo.addEvent({ reader: id, site: reader.site, type: "sync_failed", payload: { message: error.message } });
68905
+ throw error;
68906
+ } finally {
68907
+ await client.logout();
68908
+ }
68909
+ }
68910
+ async function receiveNotification(readerId, type, payload) {
68911
+ const reader = await repo.getById(readerId);
68912
+ const identityKeys = extractIdentityKeys(payload);
68913
+ const identity = await repo.findIdentity({
68914
+ reader: readerId,
68915
+ ...identityKeys
68916
+ });
68917
+ const enrichedPayload = identity ? {
68918
+ ...payload,
68919
+ identity: {
68920
+ _id: identity._id,
68921
+ type: identity.type,
68922
+ hidUserId: identity.hidUserId,
68923
+ registration: identity.registration,
68924
+ cardNo: identity.cardNo,
68925
+ person: identity.person,
68926
+ user: identity.user,
68927
+ member: identity.member,
68928
+ visitor: identity.visitor
68929
+ }
68930
+ } : {
68931
+ ...payload,
68932
+ identity: null,
68933
+ identityLookup: identityKeys
68934
+ };
68935
+ await repo.updateById(readerId, { lastSeenAt: /* @__PURE__ */ new Date() });
68936
+ return repo.addEvent({
68937
+ reader: readerId,
68938
+ site: reader.site,
68939
+ type,
68940
+ payload: enrichedPayload,
68941
+ status: identity ? "processed" : "received"
68942
+ });
68943
+ }
68944
+ async function listLogs(value) {
68945
+ return repo.listEvents(value);
68946
+ }
68947
+ async function listIdentities(value) {
68948
+ return repo.listIdentities(value);
68949
+ }
68950
+ async function createIdentity(readerId, value) {
68951
+ const reader = await repo.getById(readerId);
68952
+ return repo.addIdentity({
68953
+ ...value,
68954
+ reader: readerId,
68955
+ site: value.site || reader?.site?.toString()
68956
+ });
68957
+ }
68958
+ async function updateIdentity(identityId, value) {
68959
+ return repo.updateIdentity(identityId, value);
68960
+ }
68961
+ async function deleteIdentity(identityId) {
68962
+ return repo.deleteIdentity(identityId);
68963
+ }
68964
+ async function runObjectOperation(id, operation, payload) {
68965
+ const reader = await getActiveReader(id);
68966
+ const client = new HidAmicoClient(reader);
68967
+ try {
68968
+ await client.login();
68969
+ let result;
68970
+ if (operation === "load") {
68971
+ result = await client.loadObjects(payload);
68972
+ } else if (operation === "create") {
68973
+ result = await client.createObjects(payload);
68974
+ } else if (operation === "modify") {
68975
+ result = await client.modifyObjects(payload);
68976
+ } else {
68977
+ result = await client.destroyObjects(payload);
68978
+ }
68979
+ await repo.updateById(id, { lastSeenAt: /* @__PURE__ */ new Date() });
68980
+ await repo.addEvent({ reader: id, site: reader.site, type: `objects_${operation}`, payload: { request: payload, result } });
68981
+ return result;
68982
+ } catch (error) {
68983
+ await repo.addEvent({ reader: id, site: reader.site, type: `objects_${operation}_failed`, payload: { request: payload, message: error.message } });
68984
+ throw error;
68985
+ } finally {
68986
+ await client.logout();
68987
+ }
68988
+ }
68989
+ async function getUserImage(readerId, hidUserId) {
68990
+ const reader = await getActiveReader(readerId);
68991
+ const client = new HidAmicoClient(reader);
68992
+ try {
68993
+ await client.login();
68994
+ return await client.getUserImage(hidUserId);
68995
+ } finally {
68996
+ await client.logout();
68997
+ }
68998
+ }
68999
+ async function getDoorState(id) {
69000
+ const reader = await getActiveReader(id);
69001
+ const client = new HidAmicoClient(reader);
69002
+ try {
69003
+ await client.login();
69004
+ const state = await client.doorState();
69005
+ await repo.updateById(id, { lastSeenAt: /* @__PURE__ */ new Date() });
69006
+ await repo.addEvent({ reader: id, site: reader.site, type: "door_state", payload: state });
69007
+ return state;
69008
+ } finally {
69009
+ await client.logout();
69010
+ }
69011
+ }
69012
+ async function executeActions(id, actions) {
69013
+ const reader = await getActiveReader(id);
69014
+ const client = new HidAmicoClient(reader);
69015
+ try {
69016
+ await client.login();
69017
+ const result = await client.executeActions(actions);
69018
+ await repo.updateById(id, { lastSeenAt: /* @__PURE__ */ new Date() });
69019
+ await repo.addEvent({ reader: id, site: reader.site, type: "execute_actions", payload: { actions, result } });
69020
+ return result;
69021
+ } catch (error) {
69022
+ await repo.addEvent({ reader: id, site: reader.site, type: "execute_actions_failed", payload: { actions, message: error.message } });
69023
+ throw error;
69024
+ } finally {
69025
+ await client.logout();
69026
+ }
69027
+ }
69028
+ async function getConfiguration(id, payload) {
69029
+ const reader = await getActiveReader(id);
69030
+ const client = new HidAmicoClient(reader);
69031
+ try {
69032
+ await client.login();
69033
+ const result = await client.getConfiguration(payload);
69034
+ await repo.updateById(id, { lastSeenAt: /* @__PURE__ */ new Date() });
69035
+ await repo.addEvent({ reader: id, site: reader.site, type: "configuration", payload: { request: payload, result } });
69036
+ return result;
69037
+ } catch (error) {
69038
+ await repo.addEvent({ reader: id, site: reader.site, type: "configuration_failed", payload: { request: payload, message: error.message } });
69039
+ throw error;
69040
+ } finally {
69041
+ await client.logout();
69042
+ }
69043
+ }
69044
+ async function setConfiguration(id, payload) {
69045
+ const reader = await getActiveReader(id);
69046
+ const client = new HidAmicoClient(reader);
69047
+ try {
69048
+ await client.login();
69049
+ const result = await client.setConfiguration(payload);
69050
+ await repo.updateById(id, { lastSeenAt: /* @__PURE__ */ new Date() });
69051
+ await repo.addEvent({ reader: id, site: reader.site, type: "set_configuration", payload: { request: payload, result } });
69052
+ return result;
69053
+ } catch (error) {
69054
+ await repo.addEvent({ reader: id, site: reader.site, type: "set_configuration_failed", payload: { request: payload, message: error.message } });
69055
+ throw error;
69056
+ } finally {
69057
+ await client.logout();
69058
+ }
69059
+ }
69060
+ return {
69061
+ listReaders,
69062
+ createReader,
69063
+ updateReader,
69064
+ deleteReader,
69065
+ testReader,
69066
+ syncReader,
69067
+ receiveNotification,
69068
+ listLogs,
69069
+ listIdentities,
69070
+ createIdentity,
69071
+ updateIdentity,
69072
+ deleteIdentity,
69073
+ runObjectOperation,
69074
+ getUserImage,
69075
+ getDoorState,
69076
+ executeActions,
69077
+ getConfiguration,
69078
+ setConfiguration
69079
+ };
69080
+ }
69081
+
69082
+ // src/controllers/hid-amico.controller.ts
69083
+ import { BadRequestError as BadRequestError231 } from "@7365admin1/node-server-utils";
69084
+ function useHidAmicoController() {
69085
+ const service = useHidAmicoService();
69086
+ async function listReaders(req, res, next) {
69087
+ const { error, value } = schemaHidAmicoReaderListQuery.validate(req.query);
69088
+ if (error) {
69089
+ next(new BadRequestError231(error.message));
69090
+ return;
69091
+ }
69092
+ try {
69093
+ res.json(await service.listReaders(value));
69094
+ } catch (error2) {
69095
+ next(error2);
69096
+ }
69097
+ }
69098
+ async function createReader(req, res, next) {
69099
+ const { error, value } = schemaHidAmicoReader.validate(req.body);
69100
+ if (error) {
69101
+ next(new BadRequestError231(error.message));
69102
+ return;
69103
+ }
69104
+ try {
69105
+ res.status(201).json({ data: await service.createReader(value) });
69106
+ } catch (error2) {
69107
+ next(error2);
69108
+ }
69109
+ }
69110
+ async function updateReader(req, res, next) {
69111
+ const params = schemaHidAmicoReaderIdParams.validate(req.params);
69112
+ const body = schemaUpdateHidAmicoReader.validate(req.body);
69113
+ if (params.error || body.error) {
69114
+ next(new BadRequestError231(params.error?.message || body.error?.message));
69115
+ return;
69116
+ }
69117
+ try {
69118
+ res.json({ data: await service.updateReader(params.value.readerId, body.value) });
69119
+ } catch (error) {
69120
+ next(error);
69121
+ }
69122
+ }
69123
+ async function deleteReader(req, res, next) {
69124
+ const { error, value } = schemaHidAmicoReaderIdParams.validate(req.params);
69125
+ if (error) {
69126
+ next(new BadRequestError231(error.message));
69127
+ return;
69128
+ }
69129
+ try {
69130
+ res.json({ data: await service.deleteReader(value.readerId), message: "HID Amico reader deleted." });
69131
+ } catch (error2) {
69132
+ next(error2);
69133
+ }
69134
+ }
69135
+ async function testReader(req, res, next) {
69136
+ const { error, value } = schemaHidAmicoReaderIdParams.validate(req.params);
69137
+ if (error) {
69138
+ next(new BadRequestError231(error.message));
69139
+ return;
69140
+ }
69141
+ try {
69142
+ res.json({ data: await service.testReader(value.readerId) });
69143
+ } catch (error2) {
69144
+ next(error2);
69145
+ }
69146
+ }
69147
+ async function syncReader(req, res, next) {
69148
+ const params = schemaHidAmicoReaderIdParams.validate(req.params);
69149
+ const body = schemaHidAmicoSync.validate(req.body ?? {});
69150
+ if (params.error || body.error) {
69151
+ next(new BadRequestError231(params.error?.message || body.error?.message));
69152
+ return;
69153
+ }
69154
+ try {
69155
+ res.json({ data: await service.syncReader(params.value.readerId, body.value) });
69156
+ } catch (error) {
69157
+ next(error);
69158
+ }
69159
+ }
69160
+ async function listLogs(req, res, next) {
69161
+ const params = schemaHidAmicoReaderIdParams.validate(req.params);
69162
+ const query = schemaHidAmicoLogQuery.validate(req.query);
69163
+ if (params.error || query.error) {
69164
+ next(new BadRequestError231(params.error?.message || query.error?.message));
69165
+ return;
69166
+ }
69167
+ try {
69168
+ res.json(await service.listLogs({ reader: params.value.readerId, ...query.value }));
69169
+ } catch (error) {
69170
+ next(error);
69171
+ }
69172
+ }
69173
+ async function listIdentities(req, res, next) {
69174
+ const params = schemaHidAmicoReaderIdParams.validate(req.params);
69175
+ const query = schemaHidAmicoIdentityQuery.validate(req.query);
69176
+ if (params.error || query.error) {
69177
+ next(new BadRequestError231(params.error?.message || query.error?.message));
69178
+ return;
69179
+ }
69180
+ try {
69181
+ res.json(await service.listIdentities({ reader: params.value.readerId, ...query.value }));
69182
+ } catch (error) {
69183
+ next(error);
69184
+ }
69185
+ }
69186
+ async function createIdentity(req, res, next) {
69187
+ const params = schemaHidAmicoReaderIdParams.validate(req.params);
69188
+ if (params.error) {
69189
+ next(new BadRequestError231(params.error.message));
69190
+ return;
69191
+ }
69192
+ try {
69193
+ const body = schemaCreateHidAmicoIdentity.validate(req.body);
69194
+ if (body.error) {
69195
+ next(new BadRequestError231(body.error.message));
69196
+ return;
69197
+ }
69198
+ res.status(201).json({ data: await service.createIdentity(params.value.readerId, body.value) });
69199
+ } catch (error) {
69200
+ next(error);
69201
+ }
69202
+ }
69203
+ async function updateIdentity(req, res, next) {
69204
+ const params = schemaHidAmicoIdentityIdParams.validate(req.params);
69205
+ const body = schemaUpdateHidAmicoIdentity.validate(req.body ?? {});
69206
+ if (params.error || body.error) {
69207
+ next(new BadRequestError231(params.error?.message || body.error?.message));
69208
+ return;
69209
+ }
69210
+ try {
69211
+ res.json({ data: await service.updateIdentity(params.value.identityId, body.value) });
69212
+ } catch (error) {
69213
+ next(error);
69214
+ }
69215
+ }
69216
+ async function deleteIdentity(req, res, next) {
69217
+ const { error, value } = schemaHidAmicoIdentityIdParams.validate(req.params);
69218
+ if (error) {
69219
+ next(new BadRequestError231(error.message));
69220
+ return;
69221
+ }
69222
+ try {
69223
+ res.json({ data: await service.deleteIdentity(value.identityId), message: "HID Amico identity deleted." });
69224
+ } catch (error2) {
69225
+ next(error2);
69226
+ }
69227
+ }
69228
+ async function receiveNotification(req, res, next) {
69229
+ const validation = schemaHidAmicoNotificationParams.validate(req.params);
69230
+ if (validation.error) {
69231
+ next(new BadRequestError231(validation.error.message));
69232
+ return;
69233
+ }
69234
+ try {
69235
+ const event = await service.receiveNotification(
69236
+ validation.value.readerId,
69237
+ validation.value.type,
69238
+ req.body ?? {}
69239
+ );
69240
+ res.status(202).json({ data: event });
69241
+ } catch (error) {
69242
+ next(error);
69243
+ }
69244
+ }
69245
+ async function getDoorState(req, res, next) {
69246
+ const { error, value } = schemaHidAmicoReaderIdParams.validate(req.params);
69247
+ if (error) {
69248
+ next(new BadRequestError231(error.message));
69249
+ return;
69250
+ }
69251
+ try {
69252
+ res.json({ data: await service.getDoorState(value.readerId) });
69253
+ } catch (error2) {
69254
+ next(error2);
69255
+ }
69256
+ }
69257
+ async function getUserImage(req, res, next) {
69258
+ const { error, value } = schemaHidAmicoUserImageParams.validate(req.params);
69259
+ if (error) {
69260
+ next(new BadRequestError231(error.message));
69261
+ return;
69262
+ }
69263
+ try {
69264
+ const image = await service.getUserImage(value.readerId, value.hidUserId);
69265
+ res.json({ data: image });
69266
+ } catch (error2) {
69267
+ next(error2);
69268
+ }
69269
+ }
69270
+ async function executeActions(req, res, next) {
69271
+ const params = schemaHidAmicoReaderIdParams.validate(req.params);
69272
+ const body = schemaHidAmicoExecuteActions.validate(req.body ?? {});
69273
+ if (params.error || body.error) {
69274
+ next(new BadRequestError231(params.error?.message || body.error?.message));
69275
+ return;
69276
+ }
69277
+ try {
69278
+ res.json({ data: await service.executeActions(params.value.readerId, body.value.actions) });
69279
+ } catch (error) {
69280
+ next(error);
69281
+ }
69282
+ }
69283
+ async function getConfiguration(req, res, next) {
69284
+ const params = schemaHidAmicoReaderIdParams.validate(req.params);
69285
+ const body = schemaHidAmicoConfiguration.validate(req.body ?? {});
69286
+ if (params.error || body.error) {
69287
+ next(new BadRequestError231(params.error?.message || body.error?.message));
69288
+ return;
69289
+ }
69290
+ try {
69291
+ res.json({ data: await service.getConfiguration(params.value.readerId, body.value) });
69292
+ } catch (error) {
69293
+ next(error);
69294
+ }
69295
+ }
69296
+ async function setConfiguration(req, res, next) {
69297
+ const params = schemaHidAmicoReaderIdParams.validate(req.params);
69298
+ const body = schemaHidAmicoSetConfiguration.validate(req.body ?? {});
69299
+ if (params.error || body.error) {
69300
+ next(new BadRequestError231(params.error?.message || body.error?.message));
69301
+ return;
69302
+ }
69303
+ try {
69304
+ res.json({ data: await service.setConfiguration(params.value.readerId, body.value) });
69305
+ } catch (error) {
69306
+ next(error);
69307
+ }
69308
+ }
69309
+ async function runObjectOperation(req, res, next) {
69310
+ const params = schemaHidAmicoReaderIdParams.validate(req.params);
69311
+ const body = schemaHidAmicoObjectOperation.validate(req.body ?? {});
69312
+ if (params.error || body.error) {
69313
+ next(new BadRequestError231(params.error?.message || body.error?.message));
69314
+ return;
69315
+ }
69316
+ const { operation, ...payload } = body.value;
69317
+ if (operation === "create" && !Array.isArray(payload.values)) {
69318
+ next(new BadRequestError231("values array is required for HID object create operations."));
69319
+ return;
69320
+ }
69321
+ if (operation === "modify" && (!payload.values || Array.isArray(payload.values) || !payload.where)) {
69322
+ next(new BadRequestError231("values object and where are required for HID object modify operations."));
69323
+ return;
69324
+ }
69325
+ if (operation === "destroy" && !payload.where) {
69326
+ next(new BadRequestError231("where is required for HID object destroy operations."));
69327
+ return;
69328
+ }
69329
+ try {
69330
+ res.json({ data: await service.runObjectOperation(params.value.readerId, operation, payload) });
69331
+ } catch (error) {
69332
+ next(error);
69333
+ }
69334
+ }
69335
+ return {
69336
+ listReaders,
69337
+ createReader,
69338
+ updateReader,
69339
+ deleteReader,
69340
+ testReader,
69341
+ syncReader,
69342
+ listLogs,
69343
+ listIdentities,
69344
+ createIdentity,
69345
+ updateIdentity,
69346
+ deleteIdentity,
69347
+ receiveNotification,
69348
+ getUserImage,
69349
+ getDoorState,
69350
+ executeActions,
69351
+ getConfiguration,
69352
+ setConfiguration,
69353
+ runObjectOperation
69354
+ };
69355
+ }
67518
69356
  export {
67519
69357
  ANPRMode,
67520
69358
  AccessTypeProps,
67521
69359
  AppServiceType,
69360
+ BidStatus,
69361
+ BidType,
67522
69362
  BuildingLevelStatus,
67523
69363
  BuildingStatus,
67524
69364
  BulletinOrder,
@@ -67550,6 +69390,7 @@ export {
67550
69390
  MAddress,
67551
69391
  MAttendance,
67552
69392
  MAttendanceSettings,
69393
+ MBidPreloved,
67553
69394
  MBillingConfiguration,
67554
69395
  MBillingItem,
67555
69396
  MBuilding,
@@ -67570,6 +69411,9 @@ export {
67570
69411
  MFile,
67571
69412
  MFormEntry,
67572
69413
  MGuestManagement,
69414
+ MHidAmicoEvent,
69415
+ MHidAmicoIdentity,
69416
+ MHidAmicoReader,
67573
69417
  MIncidentReport,
67574
69418
  MManpowerDesignations,
67575
69419
  MManpowerMonitoring,
@@ -67657,7 +69501,6 @@ export {
67657
69501
  building_units_namespace_collection,
67658
69502
  buildings_namespace_collection,
67659
69503
  bulletin_boards_namespace_collection,
67660
- calculatePercentage,
67661
69504
  chatSchema,
67662
69505
  createManpowerRemarksDaily,
67663
69506
  customerSchema,
@@ -67668,7 +69511,6 @@ export {
67668
69511
  feedbacks2_namespace_collection,
67669
69512
  feedbacks_namespace_collection,
67670
69513
  formatDahuaDate,
67671
- getPeriodRangeWithPrevious,
67672
69514
  guests_namespace_collection,
67673
69515
  incidentReportLog,
67674
69516
  incidents_namespace_collection,
@@ -67691,6 +69533,7 @@ export {
67691
69533
  schema,
67692
69534
  schemaApprovedBy,
67693
69535
  schemaApprover,
69536
+ schemaBidPreloved,
67694
69537
  schemaBilling,
67695
69538
  schemaBillingConfiguration,
67696
69539
  schemaBillingItem,
@@ -67703,6 +69546,7 @@ export {
67703
69546
  schemaCategoryPreloved,
67704
69547
  schemaChannelPreloved,
67705
69548
  schemaChatPreloved,
69549
+ schemaCreateHidAmicoIdentity,
67706
69550
  schemaCustomerSite,
67707
69551
  schemaDocumentManagement,
67708
69552
  schemaEntryPassSettings,
@@ -67710,6 +69554,21 @@ export {
67710
69554
  schemaFiles,
67711
69555
  schemaFormEntry,
67712
69556
  schemaGuestManagement,
69557
+ schemaHidAmicoConfiguration,
69558
+ schemaHidAmicoEvent,
69559
+ schemaHidAmicoExecuteActions,
69560
+ schemaHidAmicoIdentity,
69561
+ schemaHidAmicoIdentityIdParams,
69562
+ schemaHidAmicoIdentityQuery,
69563
+ schemaHidAmicoLogQuery,
69564
+ schemaHidAmicoNotificationParams,
69565
+ schemaHidAmicoObjectOperation,
69566
+ schemaHidAmicoReader,
69567
+ schemaHidAmicoReaderIdParams,
69568
+ schemaHidAmicoReaderListQuery,
69569
+ schemaHidAmicoSetConfiguration,
69570
+ schemaHidAmicoSync,
69571
+ schemaHidAmicoUserImageParams,
67713
69572
  schemaIncidentReport,
67714
69573
  schemaMultipleDocumentManagement,
67715
69574
  schemaNfcPatrolLog,
@@ -67737,6 +69596,7 @@ export {
67737
69596
  schemaStatementOfAccount,
67738
69597
  schemaSubcategoryPreloved,
67739
69598
  schemaUnitBilling,
69599
+ schemaUpdateBidPreloved,
67740
69600
  schemaUpdateBuildingLevel,
67741
69601
  schemaUpdateBulletinBoard,
67742
69602
  schemaUpdateBulletinVideo,
@@ -67747,6 +69607,8 @@ export {
67747
69607
  schemaUpdateEventManagement,
67748
69608
  schemaUpdateFormEntry,
67749
69609
  schemaUpdateGuestManagement,
69610
+ schemaUpdateHidAmicoIdentity,
69611
+ schemaUpdateHidAmicoReader,
67750
69612
  schemaUpdateIncidentReport,
67751
69613
  schemaUpdateOccurrenceBook,
67752
69614
  schemaUpdateOccurrenceEntry,
@@ -67792,6 +69654,8 @@ export {
67792
69654
  useAuthControllerV2,
67793
69655
  useAuthService,
67794
69656
  useAuthServiceV2,
69657
+ useBidPrelovedController,
69658
+ useBidPrelovedRepo,
67795
69659
  useBuildingController,
67796
69660
  useBuildingLevelController,
67797
69661
  useBuildingLevelRepo,
@@ -67814,6 +69678,7 @@ export {
67814
69678
  useChatController,
67815
69679
  useChatPrelovedController,
67816
69680
  useChatPrelovedRepo,
69681
+ useChatPrelovedService,
67817
69682
  useChatRepo,
67818
69683
  useCounterModel,
67819
69684
  useCounterRepo,
@@ -67844,6 +69709,9 @@ export {
67844
69709
  useGuestManagementController,
67845
69710
  useGuestManagementRepo,
67846
69711
  useGuestManagementService,
69712
+ useHidAmicoController,
69713
+ useHidAmicoRepo,
69714
+ useHidAmicoService,
67847
69715
  useHrmLabsAttendanceCtrl,
67848
69716
  useHrmLabsAttendanceSrvc,
67849
69717
  useIncidentReportController,