@7365admin1/core 2.12.0 → 2.14.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
@@ -4759,7 +4759,8 @@ function useMemberRepo() {
4759
4759
  try {
4760
4760
  const data = await collection.find({
4761
4761
  role: { $in: roles },
4762
- type,
4762
+ // type,
4763
+ // ...(type && { type }),
4763
4764
  status: "active"
4764
4765
  }).toArray();
4765
4766
  setCache(cacheKey, data, 15 * 60).then(() => {
@@ -6880,7 +6881,7 @@ function useMemberService() {
6880
6881
  throw new BadRequestError29("No owner role found.");
6881
6882
  }
6882
6883
  const roles = owner.map((r) => r._id?.toString() ?? "");
6883
- const ownerMembers = await getByRoles(roles, type);
6884
+ const ownerMembers = await getByRoles(roles, type = "");
6884
6885
  if (!ownerMembers.length) {
6885
6886
  throw new BadRequestError29("No owner members found.");
6886
6887
  }
@@ -14674,7 +14675,7 @@ function MPerson(value) {
14674
14675
  return {
14675
14676
  _id: value._id,
14676
14677
  name: value.name,
14677
- contact: value.contact,
14678
+ contact: value.contact ?? "",
14678
14679
  block: value.block,
14679
14680
  level: value.level,
14680
14681
  unit: value.unit,
@@ -15136,7 +15137,8 @@ function usePersonRepo() {
15136
15137
  $or: [
15137
15138
  { name: { $regex: search, $options: "i" } },
15138
15139
  { email: { $regex: search, $options: "i" } },
15139
- { nric: { $regex: search, $options: "i" } }
15140
+ { nric: { $regex: search, $options: "i" } },
15141
+ { "plates.plateNumber": { $regex: search, $options: "i" } }
15140
15142
  ]
15141
15143
  },
15142
15144
  ...ObjectId44.isValid(org) && { org: new ObjectId44(org) },
@@ -18561,7 +18563,7 @@ function useVisitorTransactionService() {
18561
18563
  } else {
18562
18564
  const payload = {
18563
18565
  name: value.name || "",
18564
- contact: value.contact,
18566
+ contact: value.contact ?? "",
18565
18567
  nric,
18566
18568
  type: value.type,
18567
18569
  companyName: value.company ? [value.company] : [],
@@ -20151,7 +20153,10 @@ function usePatrolQuestionRepo() {
20151
20153
  const query = {
20152
20154
  status,
20153
20155
  ...search && {
20154
- $or: [{ name: { $regex: search, $options: "i" } }]
20156
+ $or: [
20157
+ { question: { $regex: search, $options: "i" } },
20158
+ { answers: { $regex: search, $options: "i" } }
20159
+ ]
20155
20160
  },
20156
20161
  ...ObjectId58.isValid(site) && { site: new ObjectId58(site) }
20157
20162
  };
@@ -20579,9 +20584,6 @@ function usePatrolRouteRepo() {
20579
20584
  page = page > 0 ? page - 1 : 0;
20580
20585
  const query = {
20581
20586
  status,
20582
- ...search && {
20583
- $or: [{ name: { $regex: search, $options: "i" } }]
20584
- },
20585
20587
  ...ObjectId60.isValid(site) && { site: new ObjectId60(site) }
20586
20588
  };
20587
20589
  sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
@@ -20601,14 +20603,57 @@ function usePatrolRouteRepo() {
20601
20603
  }
20602
20604
  try {
20603
20605
  const basePipeline = [
20604
- { $match: query },
20606
+ {
20607
+ $lookup: {
20608
+ from: "members",
20609
+ localField: "assignee",
20610
+ foreignField: "_id",
20611
+ as: "assigneeData"
20612
+ }
20613
+ },
20614
+ {
20615
+ $match: {
20616
+ ...query,
20617
+ ...search && {
20618
+ $or: [
20619
+ { name: { $regex: search, $options: "i" } },
20620
+ { "assigneeData.name": { $regex: search, $options: "i" } },
20621
+ { start: { $regex: search, $options: "i" } },
20622
+ { end: { $regex: search, $options: "i" } }
20623
+ ]
20624
+ }
20625
+ }
20626
+ },
20605
20627
  { $sort: sort },
20606
20628
  { $skip: page * limit },
20607
20629
  { $limit: limit }
20608
20630
  ];
20631
+ const countPipeline = [
20632
+ {
20633
+ $lookup: {
20634
+ from: "members",
20635
+ localField: "assignee",
20636
+ foreignField: "_id",
20637
+ as: "assigneeData"
20638
+ }
20639
+ },
20640
+ {
20641
+ $match: {
20642
+ ...query,
20643
+ ...search && {
20644
+ $or: [
20645
+ { name: { $regex: search, $options: "i" } },
20646
+ { "assigneeData.name": { $regex: search, $options: "i" } },
20647
+ { start: { $regex: search, $options: "i" } },
20648
+ { end: { $regex: search, $options: "i" } }
20649
+ ]
20650
+ }
20651
+ }
20652
+ }
20653
+ ];
20609
20654
  const [items, countResult] = await Promise.all([
20610
20655
  collection.aggregate(basePipeline, { session }).toArray(),
20611
- collection.aggregate([{ $match: query }, { $count: "total" }], { session }).toArray()
20656
+ collection.aggregate([...countPipeline, { $count: "total" }], { session }).toArray()
20612
20657
  ]);
20613
20658
  const totalCount = countResult[0]?.total || 0;
20614
20659
  const data = paginate27(items, page, limit, totalCount);
@@ -20717,24 +20762,16 @@ function usePatrolRouteRepo() {
20717
20762
  {
20718
20763
  $multiply: [
20719
20764
  {
20720
- $hour: {
20721
- $dateAdd: {
20722
- startDate: { $toDate: "$start" },
20723
- unit: "hour",
20724
- amount: 8
20725
- }
20765
+ $toInt: {
20766
+ $arrayElemAt: [{ $split: ["$start", ":"] }, 0]
20726
20767
  }
20727
20768
  },
20728
20769
  60
20729
20770
  ]
20730
20771
  },
20731
20772
  {
20732
- $minute: {
20733
- $dateAdd: {
20734
- startDate: { $toDate: "$start" },
20735
- unit: "hour",
20736
- amount: 8
20737
- }
20773
+ $toInt: {
20774
+ $arrayElemAt: [{ $split: ["$start", ":"] }, 1]
20738
20775
  }
20739
20776
  }
20740
20777
  ]
@@ -20747,24 +20784,16 @@ function usePatrolRouteRepo() {
20747
20784
  {
20748
20785
  $multiply: [
20749
20786
  {
20750
- $hour: {
20751
- $dateAdd: {
20752
- startDate: { $toDate: "$end" },
20753
- unit: "hour",
20754
- amount: 8
20755
- }
20787
+ $toInt: {
20788
+ $arrayElemAt: [{ $split: ["$end", ":"] }, 0]
20756
20789
  }
20757
20790
  },
20758
20791
  60
20759
20792
  ]
20760
20793
  },
20761
20794
  {
20762
- $minute: {
20763
- $dateAdd: {
20764
- startDate: { $toDate: "$end" },
20765
- unit: "hour",
20766
- amount: 8
20767
- }
20795
+ $toInt: {
20796
+ $arrayElemAt: [{ $split: ["$end", ":"] }, 1]
20768
20797
  }
20769
20798
  }
20770
20799
  ]
@@ -21102,6 +21131,8 @@ var schemeLogCamera = Joi65.object({
21102
21131
  start: Joi65.string().optional().allow("", null),
21103
21132
  end: Joi65.string().optional().allow("", null),
21104
21133
  duration: Joi65.number().optional().allow("", null),
21134
+ status: Joi65.string().optional().allow("", null),
21135
+ description: Joi65.string().optional().allow("", null),
21105
21136
  questions: Joi65.array().items(
21106
21137
  Joi65.object({
21107
21138
  questionId: Joi65.string().hex().required(),
@@ -21122,7 +21153,7 @@ var schemaPatrolLog = Joi65.object({
21122
21153
  start: Joi65.string().required(),
21123
21154
  end: Joi65.string().required(),
21124
21155
  cameras: Joi65.array().items(schemeLogCamera).required(),
21125
- status: Joi65.array().items(Joi65.string().valid("complete", "late")).required(),
21156
+ status: Joi65.array().items(Joi65.string().valid("complete", "late", "incomplete")).required(),
21126
21157
  createdAt: Joi65.date().optional(),
21127
21158
  updatedAt: Joi65.date().optional(),
21128
21159
  deletedAt: Joi65.date().optional()
@@ -21135,7 +21166,7 @@ var schemaUpdatePatrolLog = Joi65.object({
21135
21166
  start: Joi65.string().optional().allow(null, ""),
21136
21167
  end: Joi65.string().optional().allow(null, ""),
21137
21168
  cameras: Joi65.array().items(schemeLogCamera).optional().allow(null, ""),
21138
- status: Joi65.array().items(Joi65.string().valid("complete", "late")).optional().allow(null, "")
21169
+ status: Joi65.array().items(Joi65.string().valid("complete", "late", "incomplete")).optional().allow(null, "")
21139
21170
  });
21140
21171
  function MPatrolLog(value) {
21141
21172
  const { error } = schemaPatrolLog.validate(value);
@@ -21273,9 +21304,6 @@ function usePatrolLogRepo() {
21273
21304
  }, session) {
21274
21305
  page = page > 0 ? page - 1 : 0;
21275
21306
  const query = {
21276
- ...search && {
21277
- $or: [{ name: { $regex: search, $options: "i" } }]
21278
- },
21279
21307
  ...ObjectId62.isValid(site) && { site: new ObjectId62(site) }
21280
21308
  };
21281
21309
  sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
@@ -21295,14 +21323,113 @@ function usePatrolLogRepo() {
21295
21323
  }
21296
21324
  try {
21297
21325
  const basePipeline = [
21298
- { $match: query },
21326
+ {
21327
+ $lookup: {
21328
+ from: "members",
21329
+ localField: "assignee",
21330
+ foreignField: "_id",
21331
+ as: "assigneeData"
21332
+ }
21333
+ },
21334
+ {
21335
+ $match: {
21336
+ ...query,
21337
+ ...search && {
21338
+ $or: [
21339
+ { name: { $regex: search, $options: "i" } },
21340
+ { "assigneeData.name": { $regex: search, $options: "i" } },
21341
+ {
21342
+ $expr: {
21343
+ $regexMatch: {
21344
+ input: {
21345
+ $dateToString: {
21346
+ date: { $toDate: "$start" },
21347
+ format: "%H:%M",
21348
+ timezone: "Asia/Singapore"
21349
+ }
21350
+ },
21351
+ regex: search,
21352
+ options: "i"
21353
+ }
21354
+ }
21355
+ },
21356
+ {
21357
+ $expr: {
21358
+ $regexMatch: {
21359
+ input: {
21360
+ $dateToString: {
21361
+ date: { $toDate: "$start" },
21362
+ format: "%H:%M",
21363
+ timezone: "Asia/Singapore"
21364
+ }
21365
+ },
21366
+ regex: search,
21367
+ options: "i"
21368
+ }
21369
+ }
21370
+ }
21371
+ ]
21372
+ }
21373
+ }
21374
+ },
21299
21375
  { $sort: sort },
21300
21376
  { $skip: page * limit },
21301
21377
  { $limit: limit }
21302
21378
  ];
21379
+ const countPipeline = [
21380
+ {
21381
+ $lookup: {
21382
+ from: "members",
21383
+ localField: "assignee",
21384
+ foreignField: "_id",
21385
+ as: "assigneeData"
21386
+ }
21387
+ },
21388
+ {
21389
+ $match: {
21390
+ ...query,
21391
+ ...search && {
21392
+ $or: [
21393
+ { name: { $regex: search, $options: "i" } },
21394
+ { "assigneeData.name": { $regex: search, $options: "i" } },
21395
+ {
21396
+ $expr: {
21397
+ $regexMatch: {
21398
+ input: {
21399
+ $dateToString: {
21400
+ date: { $toDate: "$start" },
21401
+ format: "%H:%M",
21402
+ timezone: "Asia/Singapore"
21403
+ }
21404
+ },
21405
+ regex: search,
21406
+ options: "i"
21407
+ }
21408
+ }
21409
+ },
21410
+ {
21411
+ $expr: {
21412
+ $regexMatch: {
21413
+ input: {
21414
+ $dateToString: {
21415
+ date: { $toDate: "$start" },
21416
+ format: "%H:%M",
21417
+ timezone: "Asia/Singapore"
21418
+ }
21419
+ },
21420
+ regex: search,
21421
+ options: "i"
21422
+ }
21423
+ }
21424
+ }
21425
+ ]
21426
+ }
21427
+ }
21428
+ }
21429
+ ];
21303
21430
  const [items, countResult] = await Promise.all([
21304
21431
  collection.aggregate(basePipeline, { session }).toArray(),
21305
- collection.aggregate([{ $match: query }, { $count: "total" }], { session }).toArray()
21432
+ collection.aggregate([...countPipeline, { $count: "total" }], { session }).toArray()
21306
21433
  ]);
21307
21434
  const totalCount = countResult[0]?.total || 0;
21308
21435
  const data = paginate28(items, page, limit, totalCount);
@@ -23717,16 +23844,26 @@ function useDocumentManagementRepo() {
23717
23844
  site = ""
23718
23845
  }) {
23719
23846
  page = page > 0 ? page - 1 : 0;
23847
+ try {
23848
+ site = new ObjectId70(site);
23849
+ } catch (error) {
23850
+ throw new BadRequestError119("Invalid site ID format.");
23851
+ }
23720
23852
  sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
23721
23853
  const cacheOptions = {
23722
23854
  page,
23723
23855
  limit,
23724
23856
  status,
23857
+ site: site?.toString(),
23725
23858
  sort: JSON.stringify(sort)
23726
23859
  };
23727
23860
  const query = {
23728
23861
  ...status ? { $and: [{ status }, { status: { $ne: "deleted" } }] } : { status: { $ne: "deleted" } }
23729
23862
  };
23863
+ if (site) {
23864
+ query.site = site;
23865
+ cacheOptions.site = site;
23866
+ }
23730
23867
  if (search) {
23731
23868
  query.$or = [
23732
23869
  { name: { $regex: search, $options: "i" } },
@@ -25997,14 +26134,16 @@ var schemaEventManagement = Joi81.object({
25997
26134
  title: Joi81.string().required(),
25998
26135
  description: Joi81.string().optional().allow(""),
25999
26136
  dateTime: Joi81.alternatives().try(Joi81.string(), Joi81.date()).required(),
26000
- status: Joi81.string().optional().default("planned")
26137
+ status: Joi81.string().optional().default("planned"),
26138
+ type: Joi81.string().optional().default("TASK")
26001
26139
  });
26002
26140
  var schemaUpdateEventManagement = Joi81.object({
26003
26141
  _id: Joi81.string().hex().required(),
26004
26142
  title: Joi81.string().optional().allow(null, ""),
26005
26143
  description: Joi81.string().optional().allow(null, ""),
26006
26144
  dateTime: Joi81.alternatives().try(Joi81.string(), Joi81.date()).optional().allow(null, ""),
26007
- status: Joi81.string().optional().allow(null, "")
26145
+ status: Joi81.string().optional().allow(null, ""),
26146
+ type: Joi81.string().optional().allow(null, "")
26008
26147
  });
26009
26148
  function MEventManagement(value) {
26010
26149
  if (value._id && typeof value._id === "string") {
@@ -26028,6 +26167,7 @@ function MEventManagement(value) {
26028
26167
  description: value.description ?? "",
26029
26168
  dateTime: value.dateTime,
26030
26169
  status: value.status ?? "planned",
26170
+ type: value.type ?? "TASK",
26031
26171
  createdAt: value.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
26032
26172
  updatedAt: value.updatedAt,
26033
26173
  deletedAt: value.deletedAt
@@ -26102,7 +26242,8 @@ function useEventManagementRepo() {
26102
26242
  limit = 10,
26103
26243
  sort = {},
26104
26244
  site = "",
26105
- status = ""
26245
+ status = "",
26246
+ type = ""
26106
26247
  }, session) {
26107
26248
  page = page > 0 ? page - 1 : 0;
26108
26249
  try {
@@ -26112,7 +26253,8 @@ function useEventManagementRepo() {
26112
26253
  }
26113
26254
  const baseQuery = {
26114
26255
  site,
26115
- status: status ? status : { $ne: "deleted" }
26256
+ status: status ? status : { $ne: "deleted" },
26257
+ ...type && { type }
26116
26258
  };
26117
26259
  let query = { ...baseQuery };
26118
26260
  sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
@@ -26121,7 +26263,8 @@ function useEventManagementRepo() {
26121
26263
  status: status ? status : { $ne: "deleted" },
26122
26264
  sort: JSON.stringify(sort),
26123
26265
  page,
26124
- limit
26266
+ limit,
26267
+ ...type && { type }
26125
26268
  };
26126
26269
  if (search) {
26127
26270
  query.$text = { $search: search };
@@ -26408,7 +26551,8 @@ function useEventManagementController() {
26408
26551
  sort: Joi82.string().pattern(/^([a-zA-Z0-9_]+)(,[a-zA-Z0-9_]+)*$/).optional().allow("", ...allowedFields),
26409
26552
  order: Joi82.string().pattern(/^(asc|desc)(,(asc|desc))*$/).optional().allow("", ...allowedOrder),
26410
26553
  site: Joi82.string().hex().required(),
26411
- status: Joi82.string().optional()
26554
+ status: Joi82.string().optional(),
26555
+ type: Joi82.string().optional().valid("TASK", "EVENT").allow(null, "")
26412
26556
  });
26413
26557
  const query = { ...req.query };
26414
26558
  const { error } = validation.validate(query, {
@@ -26425,6 +26569,7 @@ function useEventManagementController() {
26425
26569
  const limit = parseInt(req.query.limit ?? "10");
26426
26570
  const site = req.query.site ?? "";
26427
26571
  const status = req.query.status ?? "";
26572
+ const type = req.query.type ?? "";
26428
26573
  const sortObj = {};
26429
26574
  const sortFields = String(req.query.sort).split(",");
26430
26575
  const sortOrders = String(req.query.order).split(",");
@@ -26441,7 +26586,8 @@ function useEventManagementController() {
26441
26586
  limit,
26442
26587
  sort: sortObj,
26443
26588
  site,
26444
- status
26589
+ status,
26590
+ type
26445
26591
  });
26446
26592
  res.status(200).json(data);
26447
26593
  return;
@@ -27400,11 +27546,12 @@ var EAccessCardTypes = /* @__PURE__ */ ((EAccessCardTypes2) => {
27400
27546
  EAccessCardTypes2["QR"] = "QRCODE";
27401
27547
  return EAccessCardTypes2;
27402
27548
  })(EAccessCardTypes || {});
27403
- var EAccessCardUserTypes = /* @__PURE__ */ ((EAccessCardUserTypes4) => {
27404
- EAccessCardUserTypes4["RESIDENT"] = "Resident/Tenant";
27405
- EAccessCardUserTypes4["CONTRACTOR"] = "Contractor";
27406
- EAccessCardUserTypes4["VISITOR"] = "Visitor";
27407
- return EAccessCardUserTypes4;
27549
+ var EAccessCardUserTypes = /* @__PURE__ */ ((EAccessCardUserTypes2) => {
27550
+ EAccessCardUserTypes2["RESIDENT"] = "Resident/Tenant";
27551
+ EAccessCardUserTypes2["CONTRACTOR"] = "Contractor";
27552
+ EAccessCardUserTypes2["VISITOR"] = "Visitor";
27553
+ EAccessCardUserTypes2["DEFAULT"] = "Visitor/Resident";
27554
+ return EAccessCardUserTypes2;
27408
27555
  })(EAccessCardUserTypes || {});
27409
27556
  var AccessTypeProps = /* @__PURE__ */ ((AccessTypeProps2) => {
27410
27557
  AccessTypeProps2["NORMAL"] = "Normal";
@@ -27505,6 +27652,114 @@ import {
27505
27652
  useAtlas as useAtlas74
27506
27653
  } from "@7365admin1/node-server-utils";
27507
27654
  import { ObjectId as ObjectId83 } from "mongodb";
27655
+
27656
+ // src/utils/access-management.ts
27657
+ import fs2 from "fs";
27658
+ import path2 from "path";
27659
+ import axios from "axios";
27660
+ import crypto from "crypto";
27661
+ var ALGORITHM = "aes-256-gcm";
27662
+ var SECRET_KEY = crypto.createSecretKey(
27663
+ new Uint8Array(crypto.createHash("sha256").update("acm-secret-key").digest())
27664
+ );
27665
+ function decryptAcmUrl(encryptedText) {
27666
+ const [ivB64, authTagB64, encryptedB64] = encryptedText.split(":");
27667
+ const iv = Buffer.from(ivB64, "base64");
27668
+ const authTag = Buffer.from(authTagB64, "base64");
27669
+ const encrypted = Buffer.from(encryptedB64, "base64");
27670
+ const decipher = crypto.createDecipheriv(
27671
+ ALGORITHM,
27672
+ SECRET_KEY,
27673
+ new Uint8Array(iv)
27674
+ );
27675
+ decipher.setAuthTag(new Uint8Array(authTag));
27676
+ const decrypted = Buffer.concat([
27677
+ decipher.update(encrypted),
27678
+ decipher.final()
27679
+ ]);
27680
+ return decrypted.toString("utf8");
27681
+ }
27682
+ var minifyXml = (xml) => {
27683
+ return xml.replace(/>\s+</g, "><").replace(/\n/g, "").replace(/\r/g, "").replace(/\t/g, "").trim();
27684
+ };
27685
+ var readTemplate = (name, params) => {
27686
+ const template = fs2.readFileSync(
27687
+ path2.join(__dirname, `../src/public/xml-templates/${name}.xml`),
27688
+ "utf-8"
27689
+ );
27690
+ if (!params)
27691
+ return minifyXml(template);
27692
+ const replacedTemplate = Object.entries(params).reduce(
27693
+ (acc, [key, value]) => acc.replace(`{{${key}}}`, value),
27694
+ template
27695
+ );
27696
+ return minifyXml(replacedTemplate);
27697
+ };
27698
+ async function sendCommand(command, url) {
27699
+ try {
27700
+ const decrypt = decryptAcmUrl(url);
27701
+ const response = await axios.post(decrypt, {
27702
+ command
27703
+ });
27704
+ if (response.status === 200 || response.status === 201)
27705
+ return response.data;
27706
+ } catch (error) {
27707
+ return Promise.reject(error);
27708
+ }
27709
+ }
27710
+ var formatDoorAccessLevels = (data) => {
27711
+ const doorAccessLevels = data.RESULT.TRACKID.SUB_RESULT.ACCESS_LEVEL;
27712
+ return doorAccessLevels.map((door) => {
27713
+ return {
27714
+ name: door._.trim(),
27715
+ // Remove any leading/trailing spaces
27716
+ no: door.$.NO
27717
+ // Extract the number
27718
+ };
27719
+ });
27720
+ };
27721
+ var formatLiftAccessLevels = (data, search) => {
27722
+ const liftAccessLevels = data.RESULT.TRACKID.SUB_RESULT.LIFT_ACCESS_LEVEL;
27723
+ const result = liftAccessLevels.map((level) => {
27724
+ return {
27725
+ name: level._.trim(),
27726
+ no: level.$.NO
27727
+ };
27728
+ });
27729
+ if (search) {
27730
+ return result.filter(
27731
+ (item) => item.name.toLowerCase().includes(search.toLowerCase())
27732
+ );
27733
+ }
27734
+ return result;
27735
+ };
27736
+ var formatAccessGroup = (data, search) => {
27737
+ const accessGroup = data.RESULT.TRACKID.SUB_RESULT.ACCESS_GROUP;
27738
+ const result = accessGroup.map((ag) => {
27739
+ return {
27740
+ no: ag._.trim(),
27741
+ name: ag.$.NAME
27742
+ };
27743
+ });
27744
+ if (search) {
27745
+ return result.filter(
27746
+ (item) => item.name.toLowerCase().includes(search.toLowerCase())
27747
+ );
27748
+ }
27749
+ return result;
27750
+ };
27751
+ var formatEntryPassDate = (date) => {
27752
+ if (!date)
27753
+ return null;
27754
+ const newDate = new Date(date);
27755
+ const year = newDate.getFullYear();
27756
+ const month = String(newDate.getMonth() + 1).padStart(2, "0");
27757
+ const day = String(newDate.getDate()).padStart(2, "0");
27758
+ return `${year}${month}${day}`;
27759
+ };
27760
+
27761
+ // src/repositories/access-management.repo.ts
27762
+ import { parseStringPromise } from "xml2js";
27508
27763
  function UseAccessManagementRepo() {
27509
27764
  function collection() {
27510
27765
  const db = useAtlas74.getDb();
@@ -27957,16 +28212,16 @@ function UseAccessManagementRepo() {
27957
28212
  preserveNullAndEmptyArrays: false
27958
28213
  }
27959
28214
  },
27960
- // Groups by unit _id and keeps only the first occurrence
27961
- {
27962
- $group: {
27963
- _id: "$level.units._id",
27964
- doc: { $first: "$$ROOT" }
27965
- }
27966
- },
27967
- {
27968
- $replaceRoot: { newRoot: "$doc" }
27969
- },
28215
+ // // Groups by unit _id and keeps only the first occurrence
28216
+ // {
28217
+ // $group: {
28218
+ // _id: "$level.units._id",
28219
+ // doc: { $first: "$$ROOT" },
28220
+ // },
28221
+ // },
28222
+ // {
28223
+ // $replaceRoot: { newRoot: "$doc" },
28224
+ // },
27970
28225
  // ✅ Apply search filter
27971
28226
  {
27972
28227
  $match: {
@@ -27978,7 +28233,6 @@ function UseAccessManagementRepo() {
27978
28233
  totalCount: [{ $count: "count" }],
27979
28234
  items: [
27980
28235
  // ✅ Sort BEFORE skip/limit for correct pagination
27981
- { $sort: { _id: -1 } },
27982
28236
  { $skip: page * limit },
27983
28237
  { $limit: limit },
27984
28238
  // ✅ Users lookup - optimized with index hint
@@ -28076,7 +28330,8 @@ function UseAccessManagementRepo() {
28076
28330
  ]
28077
28331
  }
28078
28332
  }
28079
- }
28333
+ },
28334
+ { $sort: { totalCardCount: -1 } }
28080
28335
  ]
28081
28336
  }
28082
28337
  }
@@ -28290,122 +28545,618 @@ function UseAccessManagementRepo() {
28290
28545
  await session?.endSession();
28291
28546
  }
28292
28547
  }
28293
- return {
28294
- createIndexes,
28295
- createIndexForEntrypass,
28296
- addPhysicalCardRepo,
28297
- addNonPhysicalCardRepo,
28298
- accessManagementSettingsRepo,
28299
- allAccessCardsCountsRepo,
28300
- availableAccessCardsRepo,
28301
- userTypeAccessCardsRepo,
28302
- assignedAccessCardsRepo,
28303
- acknowlegdeCardRepo
28304
- };
28305
- }
28306
-
28307
- // src/controllers/access-management.controller.ts
28308
- import Joi85 from "joi";
28309
-
28310
- // src/utils/access-management.ts
28311
- import fs2 from "fs";
28312
- import path2 from "path";
28313
- import axios from "axios";
28314
- import crypto from "crypto";
28315
- var ALGORITHM = "aes-256-gcm";
28316
- var SECRET_KEY = crypto.createSecretKey(
28317
- new Uint8Array(crypto.createHash("sha256").update("acm-secret-key").digest())
28318
- );
28319
- function decryptAcmUrl(encryptedText) {
28320
- const [ivB64, authTagB64, encryptedB64] = encryptedText.split(":");
28321
- const iv = Buffer.from(ivB64, "base64");
28322
- const authTag = Buffer.from(authTagB64, "base64");
28323
- const encrypted = Buffer.from(encryptedB64, "base64");
28324
- const decipher = crypto.createDecipheriv(
28325
- ALGORITHM,
28326
- SECRET_KEY,
28327
- new Uint8Array(iv)
28328
- );
28329
- decipher.setAuthTag(new Uint8Array(authTag));
28330
- const decrypted = Buffer.concat([
28331
- decipher.update(encrypted),
28332
- decipher.final()
28333
- ]);
28334
- return decrypted.toString("utf8");
28335
- }
28336
- var minifyXml = (xml) => {
28337
- return xml.replace(/>\s+</g, "><").replace(/\n/g, "").replace(/\r/g, "").replace(/\t/g, "").trim();
28338
- };
28339
- var readTemplate = (name, params) => {
28340
- const template = fs2.readFileSync(
28341
- path2.join(__dirname, `../src/public/xml-templates/${name}.xml`),
28342
- "utf-8"
28343
- );
28344
- if (!params)
28345
- return minifyXml(template);
28346
- const replacedTemplate = Object.entries(params).reduce(
28347
- (acc, [key, value]) => acc.replace(`{{${key}}}`, value),
28348
- template
28349
- );
28350
- return minifyXml(replacedTemplate);
28351
- };
28352
- async function sendCommand(command, url) {
28353
- try {
28354
- const decrypt = decryptAcmUrl(url);
28355
- const response = await axios.post(decrypt, {
28356
- command
28357
- });
28358
- if (response.status === 200 || response.status === 201)
28359
- return response.data;
28360
- } catch (error) {
28361
- return Promise.reject(error);
28548
+ async function accessandLiftCardsRepo(params) {
28549
+ try {
28550
+ const { accessLevel, liftAccessLevel, site, userType, type } = params;
28551
+ const siteId = new ObjectId83(site);
28552
+ const query = {
28553
+ site: { $in: [siteId] },
28554
+ userType,
28555
+ type,
28556
+ userId: null,
28557
+ assignedUnit: null,
28558
+ accessLevel,
28559
+ liftAccessLevel,
28560
+ isActivated: true
28561
+ };
28562
+ const result = await collection().aggregate([
28563
+ {
28564
+ $match: query
28565
+ },
28566
+ {
28567
+ $facet: {
28568
+ counts: [{ $count: "count" }]
28569
+ }
28570
+ }
28571
+ ], { allowDiskUse: true }).toArray();
28572
+ return result;
28573
+ } catch (error) {
28574
+ throw new Error(error.message);
28575
+ }
28362
28576
  }
28363
- }
28364
- var formatDoorAccessLevels = (data) => {
28365
- const doorAccessLevels = data.RESULT.TRACKID.SUB_RESULT.ACCESS_LEVEL;
28366
- return doorAccessLevels.map((door) => {
28367
- return {
28368
- name: door._.trim(),
28369
- // Remove any leading/trailing spaces
28370
- no: door.$.NO
28371
- // Extract the number
28372
- };
28373
- });
28374
- };
28375
- var formatLiftAccessLevels = (data, search) => {
28376
- const liftAccessLevels = data.RESULT.TRACKID.SUB_RESULT.LIFT_ACCESS_LEVEL;
28377
- const result = liftAccessLevels.map((level) => {
28378
- return {
28379
- name: level._.trim(),
28380
- no: level.$.NO
28381
- };
28382
- });
28383
- if (search) {
28384
- return result.filter(
28385
- (item) => item.name.toLowerCase().includes(search.toLowerCase())
28386
- );
28577
+ async function replaceCardRepo(params) {
28578
+ const session = useAtlas74.getClient()?.startSession();
28579
+ try {
28580
+ session?.startTransaction();
28581
+ const siteId = new ObjectId83(params.site);
28582
+ const userId = new ObjectId83(params.userId);
28583
+ const cardId = new ObjectId83(params.cardId);
28584
+ const quantity = 1;
28585
+ const cardCredentials = await collection().findOneAndUpdate(
28586
+ { _id: cardId },
28587
+ { $set: { replacementStatus: "Issuance" } },
28588
+ { returnDocument: "after" }
28589
+ );
28590
+ const unit = [cardCredentials?.assignedUnit];
28591
+ const date = /* @__PURE__ */ new Date();
28592
+ const endDate = new Date(date.setFullYear(date.getFullYear() + 10));
28593
+ const res = await collection().aggregate([{ $sort: { cardNo: -1 } }, { $limit: 2 }]).toArray();
28594
+ const prevCard = res && res?.[1]?.cardNo || "-1";
28595
+ const currentCard = res && res?.[0]?.cardNo || "0";
28596
+ let availableCardNo = [];
28597
+ let num = parseInt(prevCard, 10) + 1;
28598
+ while (availableCardNo.length < (unit.length > 0 ? unit.length : quantity)) {
28599
+ if (num === parseInt(currentCard, 10)) {
28600
+ num++;
28601
+ }
28602
+ availableCardNo.push(num);
28603
+ num++;
28604
+ }
28605
+ const cardNumbers = availableCardNo.map((no) => no.toString().padStart(10, "0"));
28606
+ const accessCards = [];
28607
+ const convertedUnits = unit.map((obj) => new ObjectId83(obj));
28608
+ for (let j = 0; j < (unit.length > 0 ? unit.length : quantity); j++) {
28609
+ accessCards.push(
28610
+ new MAccessCard({
28611
+ userId,
28612
+ site: siteId,
28613
+ type: cardCredentials?.type,
28614
+ accessLevel: cardCredentials?.accessLevel,
28615
+ accessGroup: cardCredentials?.accessGroup,
28616
+ accessType: cardCredentials?.accessType,
28617
+ cardNo: cardNumbers[j],
28618
+ pin: "123456",
28619
+ qrData: "092222",
28620
+ startDate: /* @__PURE__ */ new Date(),
28621
+ endDate,
28622
+ isActivated: true,
28623
+ isAntiPassBack: false,
28624
+ isLiftCard: cardCredentials?.isLiftCard ? true : false,
28625
+ liftAccessLevel: cardCredentials?.liftAccessLevel,
28626
+ userType: cardCredentials?.userType,
28627
+ doorName: cardCredentials?.doorName,
28628
+ liftName: cardCredentials?.liftName,
28629
+ assignedUnit: convertedUnits[j],
28630
+ replacementStatus: "Issuance",
28631
+ createdAt: /* @__PURE__ */ new Date(),
28632
+ updatedAt: /* @__PURE__ */ new Date()
28633
+ })
28634
+ );
28635
+ }
28636
+ const commands = accessCards.map((item, index) => {
28637
+ let ag = null;
28638
+ if (item.accessGroup !== void 0) {
28639
+ if (item.accessGroup?.length > 0) {
28640
+ ag = item.accessGroup.map((g) => `<GROUP_NAME>${g}</GROUP_NAME>`).join("\n ");
28641
+ }
28642
+ }
28643
+ const command = {
28644
+ commandId1: index * 2 + 1,
28645
+ commandId2: index * 2 + 2,
28646
+ staffName: `STAFF-${item._id.toString().slice(-10)}`,
28647
+ staffNo1: `STAFF-${item._id.toString().slice(-10)}`,
28648
+ staffNo2: `STAFF-${item._id.toString().slice(-10)}`,
28649
+ dateOfJoin: formatEntryPassDate(item.startDate),
28650
+ accessLevel: item.accessLevel ?? "0",
28651
+ cardNo: item.cardNo,
28652
+ pin: typeof item.pin === "string" && item.pin.trim() !== "" ? item.pin : "123456",
28653
+ startDate: formatEntryPassDate(item.startDate),
28654
+ endDate: formatEntryPassDate(item.endDate),
28655
+ cardType: 0,
28656
+ isActivated: item.isActivated ? 1 : 0,
28657
+ isAntiPassBack: item.isAntiPassBack ? 1 : 0,
28658
+ isLiftCard: item.isLiftCard ? 1 : 0,
28659
+ isLiftActivate: item.isLiftCard ? 1 : 0,
28660
+ liftAccessLevel: item.liftAccessLevel || 1,
28661
+ liftAccessStartDate: formatEntryPassDate(item.liftAccessStartDate) || "19770510",
28662
+ liftAccessEndDate: formatEntryPassDate(item.liftAccessEndDate) || "19770510",
28663
+ accessGroup: ag
28664
+ };
28665
+ return readTemplate(`${item.accessLevel !== null ? "add-card" : "add-card-lift"}`, { ...command });
28666
+ }).flat();
28667
+ const response = await sendCommand(commands.join("").toString(), params.acm_url);
28668
+ const result = await parseStringPromise(response, { explicitArray: false });
28669
+ if (result && result.RESULT.$.STCODE !== "0") {
28670
+ throw new Error("Command failed, server error.");
28671
+ }
28672
+ const card = await collection().insertMany(accessCards);
28673
+ await session?.commitTransaction();
28674
+ return card;
28675
+ } catch (error) {
28676
+ await session?.abortTransaction();
28677
+ throw new Error(error.message);
28678
+ } finally {
28679
+ await session?.endSession();
28680
+ }
28387
28681
  }
28388
- return result;
28389
- };
28390
- var formatAccessGroup = (data, search) => {
28391
- const accessGroup = data.RESULT.TRACKID.SUB_RESULT.ACCESS_GROUP;
28392
- const result = accessGroup.map((ag) => {
28393
- return {
28394
- no: ag._.trim(),
28395
- name: ag.$.NAME
28396
- };
28397
- });
28398
- if (search) {
28399
- return result.filter(
28400
- (item) => item.name.toLowerCase().includes(search.toLowerCase())
28401
- );
28682
+ async function updateNFCStatusRepo(params) {
28683
+ const session = useAtlas74.getClient()?.startSession();
28684
+ try {
28685
+ session?.startTransaction();
28686
+ const results = [];
28687
+ for (let nfc of params.nfcList) {
28688
+ nfc._id = new ObjectId83(nfc._id);
28689
+ const card = await collection().findOne({ _id: nfc._id }, { session });
28690
+ if (card) {
28691
+ const updateFields = {
28692
+ status: nfc.status,
28693
+ vmsRemarks: nfc?.vmsRemarks,
28694
+ userId: null,
28695
+ updatedAt: nfc?.updatedAt ?? /* @__PURE__ */ new Date()
28696
+ };
28697
+ if (nfc.status !== "Returned") {
28698
+ updateFields.isActivated = false;
28699
+ } else {
28700
+ updateFields.isActivated = true;
28701
+ }
28702
+ const res = await collection().updateOne({ _id: card._id }, { $set: updateFields }, { session });
28703
+ results.push({ nfcId: nfc._id, modifiedCount: res.modifiedCount });
28704
+ }
28705
+ }
28706
+ await session?.commitTransaction();
28707
+ return results;
28708
+ } catch (error) {
28709
+ await session?.abortTransaction();
28710
+ throw new Error(error.message);
28711
+ } finally {
28712
+ await session?.endSession();
28713
+ }
28402
28714
  }
28403
- return result;
28404
- };
28715
+ async function doorAndLiftDropdownRepo(params) {
28716
+ try {
28717
+ const { site, type, userType } = params;
28718
+ const id = new ObjectId83(site);
28719
+ const res = collection().aggregate([
28720
+ {
28721
+ $match: {
28722
+ site: { $in: [id] },
28723
+ type,
28724
+ userType,
28725
+ isActivated: true,
28726
+ assignedUnit: null,
28727
+ userId: null,
28728
+ $or: [
28729
+ { $and: [{ doorName: { $ne: null } }, { doorName: { $ne: "" } }, { accessLevel: { $ne: null } }] },
28730
+ { $and: [{ liftName: { $ne: null } }, { liftName: { $ne: "" } }, { liftAccessLevel: { $ne: null } }] }
28731
+ ]
28732
+ }
28733
+ },
28734
+ {
28735
+ $facet: {
28736
+ totalCount: [{ $count: "count" }],
28737
+ accessData: [
28738
+ {
28739
+ $group: {
28740
+ _id: null,
28741
+ accessLevels: {
28742
+ $addToSet: {
28743
+ $cond: [
28744
+ { $and: [{ $ne: ["$doorName", null] }, { $ne: ["$doorName", ""] }, { $ne: ["$accessLevel", null] }] },
28745
+ { name: "$doorName", no: "$accessLevel" },
28746
+ "$$REMOVE"
28747
+ ]
28748
+ }
28749
+ },
28750
+ liftAccessLevels: {
28751
+ $addToSet: {
28752
+ $cond: [
28753
+ { $and: [{ $ne: ["$liftName", null] }, { $ne: ["$liftName", ""] }, { $ne: ["$liftAccessLevel", null] }] },
28754
+ { name: "$liftName", no: "$liftAccessLevel" },
28755
+ "$$REMOVE"
28756
+ ]
28757
+ }
28758
+ }
28759
+ }
28760
+ },
28761
+ {
28762
+ $project: {
28763
+ _id: 0,
28764
+ accessLevels: 1,
28765
+ liftAccessLevels: 1
28766
+ }
28767
+ }
28768
+ ]
28769
+ }
28770
+ }
28771
+ ]).toArray();
28772
+ return res;
28773
+ } catch (error) {
28774
+ throw new Error(error.message);
28775
+ }
28776
+ }
28777
+ async function cardReplacementRepo(params) {
28778
+ const session = useAtlas74.getClient()?.startSession();
28779
+ try {
28780
+ const { cardId, remarks } = params;
28781
+ const id = new ObjectId83(cardId);
28782
+ session?.startTransaction();
28783
+ const card = await collection().findOneAndUpdate(
28784
+ { _id: id },
28785
+ { $set: { remarks, replacementStatus: "Pending", requestDate: /* @__PURE__ */ new Date(), isActivated: false } },
28786
+ { returnDocument: "after", session }
28787
+ );
28788
+ await session?.commitTransaction();
28789
+ return card;
28790
+ } catch (error) {
28791
+ await session?.abortTransaction();
28792
+ throw new Error(error.message);
28793
+ } finally {
28794
+ await session?.endSession();
28795
+ }
28796
+ }
28797
+ async function visitorAccessCardsRepo(params) {
28798
+ try {
28799
+ const page = params.page ? params.page - 1 : 0;
28800
+ const siteId = new ObjectId83(params.site);
28801
+ const search = params.search;
28802
+ const type = params.type;
28803
+ const limit = Number(params.limit);
28804
+ const query = {
28805
+ site: siteId,
28806
+ assignedUnit: { $ne: null },
28807
+ type: "NFC" /* NFC */
28808
+ };
28809
+ if (search) {
28810
+ query.$or = [{ accessLevel: { $regex: search, $options: "i" } }, { cardNo: { $regex: search, $options: "i" } }];
28811
+ }
28812
+ if (type) {
28813
+ query.userType = type;
28814
+ } else {
28815
+ query.userType = { $ne: "Resident/Tenant" /* RESIDENT */ };
28816
+ }
28817
+ const res = await collection().aggregate([
28818
+ {
28819
+ $match: query
28820
+ },
28821
+ {
28822
+ $project: {
28823
+ cardNo: 1,
28824
+ accessLevel: 1,
28825
+ site: 1,
28826
+ userType: 1,
28827
+ qrTag: 1,
28828
+ qrTagCardNo: 1,
28829
+ qrData: 1
28830
+ }
28831
+ },
28832
+ {
28833
+ $addFields: {
28834
+ extractedCardNo: {
28835
+ $substr: ["$cardNo", { $subtract: [{ $strLenCP: "$cardNo" }, 5] }, 5]
28836
+ }
28837
+ }
28838
+ },
28839
+ {
28840
+ $facet: {
28841
+ totalCount: [{ $count: "count" }],
28842
+ items: [{ $sort: { _id: -1 } }, { $skip: page * limit }, { $limit: limit }]
28843
+ }
28844
+ }
28845
+ ]).toArray();
28846
+ const length = res[0].totalCount[0] ? res[0].totalCount[0].count : 0;
28847
+ const items = res[0].items;
28848
+ const paginatedResult = paginate38(items, page, limit, length);
28849
+ return paginatedResult;
28850
+ } catch (error) {
28851
+ throw new Error(error.message);
28852
+ }
28853
+ }
28854
+ async function getCardReplacementRepo(params) {
28855
+ try {
28856
+ const site = new ObjectId83(params.site);
28857
+ const search = params.search;
28858
+ const statusFilter = params.statusFilter;
28859
+ const dateFrom = params.dateFrom;
28860
+ const dateTo = params.dateTo;
28861
+ const page = Number(params.page) - 1;
28862
+ const limit = Number(params.limit);
28863
+ const query = {
28864
+ site,
28865
+ replacementStatus: { $in: ["Complete", "Issuance", "Pending"] },
28866
+ isActivated: false
28867
+ };
28868
+ const searchQuery = buildSearchQuery(search);
28869
+ if (statusFilter) {
28870
+ query.replacementStatus = statusFilter;
28871
+ }
28872
+ if (dateFrom && dateTo) {
28873
+ query.requestDate = { $gte: new Date(dateFrom), $lte: new Date(dateTo) };
28874
+ } else if (dateFrom) {
28875
+ query.requestDate = { $gte: new Date(dateFrom) };
28876
+ } else if (dateTo) {
28877
+ query.requestDate = { $lte: new Date(dateTo) };
28878
+ }
28879
+ const res = await collection().aggregate([
28880
+ {
28881
+ $match: { ...query }
28882
+ },
28883
+ {
28884
+ $lookup: {
28885
+ from: "building-units",
28886
+ let: { unit: "$assignedUnit" },
28887
+ pipeline: [
28888
+ {
28889
+ $match: {
28890
+ $expr: {
28891
+ $eq: ["$_id", "$$unit"]
28892
+ }
28893
+ }
28894
+ },
28895
+ {
28896
+ $project: {
28897
+ _id: 1,
28898
+ name: 1,
28899
+ level: 1
28900
+ }
28901
+ }
28902
+ ],
28903
+ as: "unit"
28904
+ }
28905
+ },
28906
+ {
28907
+ $unwind: { path: "$unit", preserveNullAndEmptyArrays: true }
28908
+ },
28909
+ {
28910
+ $lookup: {
28911
+ from: "building-levels",
28912
+ let: { level: "$unit.level" },
28913
+ pipeline: [
28914
+ {
28915
+ $match: {
28916
+ $expr: {
28917
+ $eq: ["$_id", "$$level"]
28918
+ }
28919
+ }
28920
+ },
28921
+ {
28922
+ $project: {
28923
+ _id: 1,
28924
+ level: 1,
28925
+ block: 1
28926
+ }
28927
+ }
28928
+ ],
28929
+ as: "level"
28930
+ }
28931
+ },
28932
+ {
28933
+ $unwind: { path: "$level", preserveNullAndEmptyArrays: true }
28934
+ },
28935
+ {
28936
+ $lookup: {
28937
+ from: "buildings",
28938
+ let: { block: "$level.block" },
28939
+ pipeline: [
28940
+ {
28941
+ $match: {
28942
+ $expr: {
28943
+ $eq: ["$_id", "$$block"]
28944
+ }
28945
+ }
28946
+ },
28947
+ {
28948
+ $project: {
28949
+ _id: 1,
28950
+ name: 1
28951
+ }
28952
+ }
28953
+ ],
28954
+ as: "building"
28955
+ }
28956
+ },
28957
+ {
28958
+ $unwind: { path: "$building", preserveNullAndEmptyArrays: true }
28959
+ },
28960
+ {
28961
+ $lookup: {
28962
+ from: "users",
28963
+ let: { id: "$userId" },
28964
+ pipeline: [
28965
+ {
28966
+ $match: {
28967
+ $expr: {
28968
+ $eq: ["$_id", "$$id"]
28969
+ }
28970
+ }
28971
+ },
28972
+ {
28973
+ $project: {
28974
+ givenName: 1,
28975
+ surname: 1
28976
+ }
28977
+ }
28978
+ ],
28979
+ as: "user"
28980
+ }
28981
+ },
28982
+ {
28983
+ $unwind: { path: "$user", preserveNullAndEmptyArrays: true }
28984
+ },
28985
+ {
28986
+ $match: { ...searchQuery }
28987
+ },
28988
+ {
28989
+ $facet: {
28990
+ data: [
28991
+ { $skip: page * limit },
28992
+ { $limit: limit },
28993
+ {
28994
+ $project: {
28995
+ _id: 1,
28996
+ cardNo: 1,
28997
+ accessLevel: 1,
28998
+ liftAccessLevel: 1,
28999
+ replacementStatus: 1,
29000
+ remarks: 1,
29001
+ block: "$building.name",
29002
+ level: "$level.level",
29003
+ unit: "$unit.name",
29004
+ user: "$user"
29005
+ }
29006
+ }
29007
+ ],
29008
+ totalCount: [{ $count: "count" }]
29009
+ }
29010
+ }
29011
+ ], { allowDiskUse: true }).toArray();
29012
+ const count = res[0]?.totalCount[0] ? res[0].totalCount[0].count : 0;
29013
+ const pagination = paginate38(res[0].data, page, limit, count);
29014
+ return pagination;
29015
+ } catch (error) {
29016
+ throw new Error(error.message);
29017
+ }
29018
+ }
29019
+ async function getAccessManagementSettingsRepo(params) {
29020
+ try {
29021
+ const { site } = params;
29022
+ const siteId = new ObjectId83(site);
29023
+ const res = await collectionName("entrypass-settings").findOne({ site: siteId }, { allowDiskUse: true });
29024
+ return res;
29025
+ } catch (error) {
29026
+ throw new Error(error.message);
29027
+ }
29028
+ }
29029
+ async function bulkPhysicalAccessCardRepo(params) {
29030
+ const session = useAtlas74.getClient()?.startSession();
29031
+ try {
29032
+ const { dataJson, site } = params;
29033
+ const rawItems = JSON.parse(dataJson).filter((_, index) => index !== -1);
29034
+ const items = await Promise.all(
29035
+ rawItems.map(async (item) => {
29036
+ const date = new Date(item["startDate (format MM/DD/YYYY)"]);
29037
+ const endDate = new Date(date.setFullYear(date.getFullYear() + 10));
29038
+ const cardNumber = item["cardNo (number 0-65535 ex. 301)"].toString().padStart(10, "0");
29039
+ const pin = item["pin (number 6 digits only)"] ? item["pin (number 6 digits only)"].toString().padStart(6, "0") : "123456";
29040
+ const match = item["accessLevel (number ex. 1)"];
29041
+ const accessLevel = match ? match : null;
29042
+ const userType = item["userType(Contractor, Visitor, Resident/Tenant, Visitor/Resident)"];
29043
+ const rawAccessGroup = item["accessGroup (value ex. Full Access, No Access)"];
29044
+ const accessGroup = typeof rawAccessGroup === "string" ? rawAccessGroup.split(",").map((v) => v.trim()).filter((v) => v !== "") : [];
29045
+ return new MAccessCard({
29046
+ site: new ObjectId83(site),
29047
+ type: "NFC" /* NFC */,
29048
+ staffNo: null,
29049
+ accessLevel,
29050
+ accessGroup,
29051
+ accessType: "Normal" /* NORMAL */,
29052
+ cardNo: cardNumber,
29053
+ pin,
29054
+ qrData: await createQrData({ cardNumber }),
29055
+ startDate: new Date(item["startDate (format MM/DD/YYYY)"]),
29056
+ endDate: new Date(item["endDate (format MM/DD/YYYY)"] || endDate),
29057
+ isActivated: true,
29058
+ isAntiPassBack: false,
29059
+ isLiftCard: item["isLiftCard (TRUE OR FALSE)"] === "TRUE" ? true : false,
29060
+ liftAccessLevel: item["liftAccessLevel(number ex. 1)"] || null,
29061
+ createdAt: /* @__PURE__ */ new Date(),
29062
+ updatedAt: /* @__PURE__ */ new Date(),
29063
+ assignedUnit: null,
29064
+ userType: userType.toLowerCase() === "contractor" ? "Contractor" /* CONTRACTOR */ : userType.toLowerCase() === "visitor" ? "Visitor" /* VISITOR */ : userType.toLowerCase() === "resident/tenant" ? "Resident/Tenant" /* RESIDENT */ : "Visitor/Resident" /* DEFAULT */,
29065
+ doorName: item["Door Name (ex. Main Door)"] || null,
29066
+ liftName: item["Lift Name (ex. Main Lift)"] || null
29067
+ });
29068
+ })
29069
+ );
29070
+ const result = await collection().insertMany(items, { session, ordered: false });
29071
+ const mapping = items.map((item, i) => ({
29072
+ cardNo: item.cardNo,
29073
+ insertedId: result.insertedIds[i]
29074
+ }));
29075
+ return mapping;
29076
+ } catch (error) {
29077
+ throw new Error(error.message);
29078
+ }
29079
+ }
29080
+ async function assignAccessCardToUnitRepo(params) {
29081
+ const session = useAtlas74.getClient()?.startSession();
29082
+ try {
29083
+ session?.startTransaction();
29084
+ const { units, quantity, type, site, userType, accessLevel, liftAccessLevel } = params;
29085
+ const [convertedUnits, convertedSite] = await Promise.all([Promise.all(units.map((id) => new ObjectId83(id))), new ObjectId83(site)]);
29086
+ const totalRequired = quantity * convertedUnits.length;
29087
+ const availableCards = await collection().find({
29088
+ assignedUnit: null,
29089
+ userId: null,
29090
+ type,
29091
+ userType,
29092
+ isActivated: true,
29093
+ site: convertedSite,
29094
+ accessLevel: accessLevel ?? null,
29095
+ liftAccessLevel: liftAccessLevel ?? null
29096
+ }).limit(totalRequired).toArray();
29097
+ if (availableCards.length < totalRequired) {
29098
+ session?.abortTransaction();
29099
+ return {
29100
+ status: "error",
29101
+ message: `Insufficient ${type} access cards. Need ${totalRequired}, but only ${availableCards.length} available.`
29102
+ };
29103
+ }
29104
+ const bulkUpdates = availableCards.map((card, index) => ({
29105
+ updateOne: {
29106
+ filter: { _id: card._id },
29107
+ update: {
29108
+ $set: {
29109
+ assignedUnit: convertedUnits[Math.floor(index / quantity)]
29110
+ }
29111
+ }
29112
+ }
29113
+ }));
29114
+ await collection().bulkWrite(bulkUpdates, { session });
29115
+ session?.commitTransaction();
29116
+ return {
29117
+ status: "success",
29118
+ message: "Cards assigned to units successfully.",
29119
+ assigned: bulkUpdates.length
29120
+ };
29121
+ } catch (error) {
29122
+ session?.abortTransaction();
29123
+ return Promise.reject(error.message);
29124
+ } finally {
29125
+ session?.endSession();
29126
+ }
29127
+ }
29128
+ return {
29129
+ createIndexes,
29130
+ createIndexForEntrypass,
29131
+ addPhysicalCardRepo,
29132
+ addNonPhysicalCardRepo,
29133
+ accessManagementSettingsRepo,
29134
+ allAccessCardsCountsRepo,
29135
+ availableAccessCardsRepo,
29136
+ userTypeAccessCardsRepo,
29137
+ assignedAccessCardsRepo,
29138
+ acknowlegdeCardRepo,
29139
+ accessandLiftCardsRepo,
29140
+ replaceCardRepo,
29141
+ updateNFCStatusRepo,
29142
+ doorAndLiftDropdownRepo,
29143
+ cardReplacementRepo,
29144
+ visitorAccessCardsRepo,
29145
+ getCardReplacementRepo,
29146
+ getAccessManagementSettingsRepo,
29147
+ bulkPhysicalAccessCardRepo,
29148
+ assignAccessCardToUnitRepo
29149
+ };
29150
+ }
29151
+
29152
+ // src/controllers/access-management.controller.ts
29153
+ import Joi85 from "joi";
28405
29154
 
28406
29155
  // src/services/access-management.service.ts
28407
- import { parseStringPromise } from "xml2js";
29156
+ import { parseStringPromise as parseStringPromise2 } from "xml2js";
28408
29157
  import { useCache as useCache47 } from "@7365admin1/node-server-utils";
29158
+ import { Readable } from "stream";
29159
+ import * as xlsx from "xlsx";
28409
29160
  var namespace = "cache:acm";
28410
29161
  function useAccessManagementSvc() {
28411
29162
  const {
@@ -28416,7 +29167,17 @@ function useAccessManagementSvc() {
28416
29167
  availableAccessCardsRepo,
28417
29168
  userTypeAccessCardsRepo,
28418
29169
  assignedAccessCardsRepo,
28419
- acknowlegdeCardRepo
29170
+ acknowlegdeCardRepo,
29171
+ accessandLiftCardsRepo,
29172
+ replaceCardRepo,
29173
+ updateNFCStatusRepo,
29174
+ doorAndLiftDropdownRepo,
29175
+ cardReplacementRepo,
29176
+ visitorAccessCardsRepo,
29177
+ getCardReplacementRepo,
29178
+ getAccessManagementSettingsRepo,
29179
+ bulkPhysicalAccessCardRepo,
29180
+ assignAccessCardToUnitRepo
28420
29181
  } = UseAccessManagementRepo();
28421
29182
  const addPhysicalCardSvc = async (payload) => {
28422
29183
  try {
@@ -28458,7 +29219,7 @@ function useAccessManagementSvc() {
28458
29219
  }
28459
29220
  const command = readTemplate("door-levels");
28460
29221
  const response = await sendCommand(command, params.acm_url);
28461
- const res = await parseStringPromise(response, { explicitArray: false });
29222
+ const res = await parseStringPromise2(response, { explicitArray: false });
28462
29223
  const format = await formatDoorAccessLevels(res);
28463
29224
  await setCache({ key, data: format, ttlSeconds: 60, redis });
28464
29225
  redis.lrem(listKey, 0, key).then(() => redis.lpush(listKey, key)).then(() => redis.ltrim(listKey, 0, 9)).catch(console.error);
@@ -28481,7 +29242,7 @@ function useAccessManagementSvc() {
28481
29242
  }
28482
29243
  const command = readTemplate("lift-levels");
28483
29244
  const response = await sendCommand(command, params.acm_url);
28484
- const res = await parseStringPromise(response, { explicitArray: false });
29245
+ const res = await parseStringPromise2(response, { explicitArray: false });
28485
29246
  const format = await formatLiftAccessLevels(res);
28486
29247
  await setCache({ key, data: format, ttlSeconds: 60, redis });
28487
29248
  redis.lrem(listKey, 0, key).then(() => redis.lpush(listKey, key)).then(() => redis.ltrim(listKey, 0, 9)).catch(console.error);
@@ -28504,7 +29265,7 @@ function useAccessManagementSvc() {
28504
29265
  }
28505
29266
  const command = readTemplate("access-group");
28506
29267
  const response = await sendCommand(command, params.acm_url);
28507
- const res = await parseStringPromise(response, { explicitArray: false });
29268
+ const res = await parseStringPromise2(response, { explicitArray: false });
28508
29269
  const format = await formatAccessGroup(res);
28509
29270
  await setCache({ key, data: format, ttlSeconds: 60, redis });
28510
29271
  redis.lrem(listKey, 0, key).then(() => redis.lpush(listKey, key)).then(() => redis.ltrim(listKey, 0, 9)).catch(console.error);
@@ -28513,49 +29274,152 @@ function useAccessManagementSvc() {
28513
29274
  throw new Error(err.message);
28514
29275
  }
28515
29276
  };
28516
- const accessManagementSettingsSvc = async (settings) => {
29277
+ const accessManagementSettingsSvc = async (settings) => {
29278
+ try {
29279
+ const response = await accessManagementSettingsRepo({ ...settings });
29280
+ return response;
29281
+ } catch (err) {
29282
+ throw new Error(err.message);
29283
+ }
29284
+ };
29285
+ const allAccessCardsCountsSvc = async (params) => {
29286
+ try {
29287
+ const response = await allAccessCardsCountsRepo({ ...params });
29288
+ return response;
29289
+ } catch (err) {
29290
+ throw new Error(err.message);
29291
+ }
29292
+ };
29293
+ const availableAccessCardsSvc = async (params) => {
29294
+ try {
29295
+ const response = await availableAccessCardsRepo({ ...params });
29296
+ return response;
29297
+ } catch (err) {
29298
+ throw new Error(err.message);
29299
+ }
29300
+ };
29301
+ const userTypeAccessCardsSvc = async (params) => {
29302
+ try {
29303
+ const response = await userTypeAccessCardsRepo({ ...params });
29304
+ return response;
29305
+ } catch (err) {
29306
+ throw new Error(err.message);
29307
+ }
29308
+ };
29309
+ const assignedAccessCardsSvc = async (params) => {
29310
+ try {
29311
+ const response = await assignedAccessCardsRepo({ ...params });
29312
+ return response;
29313
+ } catch (err) {
29314
+ throw new Error(err.message);
29315
+ }
29316
+ };
29317
+ const acknowlegdeCardSvc = async (params) => {
29318
+ try {
29319
+ const response = await acknowlegdeCardRepo({ ...params });
29320
+ return response;
29321
+ } catch (err) {
29322
+ throw new Error(err.message);
29323
+ }
29324
+ };
29325
+ const accessandLiftCardsSvc = async (params) => {
29326
+ try {
29327
+ const response = await accessandLiftCardsRepo({ ...params });
29328
+ return response;
29329
+ } catch (err) {
29330
+ throw new Error(err.message);
29331
+ }
29332
+ };
29333
+ const replaceCardSvc = async (params) => {
29334
+ try {
29335
+ const response = await replaceCardRepo({ ...params });
29336
+ return response;
29337
+ } catch (err) {
29338
+ throw new Error(err.message);
29339
+ }
29340
+ };
29341
+ const updateNFCStatusSvc = async (params) => {
28517
29342
  try {
28518
- const response = await accessManagementSettingsRepo({ ...settings });
29343
+ const response = await updateNFCStatusRepo({ ...params });
28519
29344
  return response;
28520
29345
  } catch (err) {
28521
29346
  throw new Error(err.message);
28522
29347
  }
28523
29348
  };
28524
- const allAccessCardsCountsSvc = async (params) => {
29349
+ const doorAndLiftDropdownSvc = async (params) => {
28525
29350
  try {
28526
- const response = await allAccessCardsCountsRepo({ ...params });
29351
+ const response = await doorAndLiftDropdownRepo({ ...params });
28527
29352
  return response;
28528
29353
  } catch (err) {
28529
29354
  throw new Error(err.message);
28530
29355
  }
28531
29356
  };
28532
- const availableAccessCardsSvc = async (params) => {
29357
+ const cardReplacementSvc = async (params) => {
28533
29358
  try {
28534
- const response = await availableAccessCardsRepo({ ...params });
29359
+ const response = await cardReplacementRepo({ ...params });
28535
29360
  return response;
28536
29361
  } catch (err) {
28537
29362
  throw new Error(err.message);
28538
29363
  }
28539
29364
  };
28540
- const userTypeAccessCardsSvc = async (params) => {
29365
+ const visitorAccessCardsSvc = async (params) => {
28541
29366
  try {
28542
- const response = await userTypeAccessCardsRepo({ ...params });
29367
+ const response = await visitorAccessCardsRepo({ ...params });
28543
29368
  return response;
28544
29369
  } catch (err) {
28545
29370
  throw new Error(err.message);
28546
29371
  }
28547
29372
  };
28548
- const assignedAccessCardsSvc = async (params) => {
29373
+ const getCardReplacementSvc = async (params) => {
28549
29374
  try {
28550
- const response = await assignedAccessCardsRepo({ ...params });
29375
+ const response = await getCardReplacementRepo({ ...params });
28551
29376
  return response;
28552
29377
  } catch (err) {
28553
29378
  throw new Error(err.message);
28554
29379
  }
28555
29380
  };
28556
- const acknowlegdeCardSvc = async (params) => {
29381
+ const getAccessManagementSettingsSvc = async (params) => {
28557
29382
  try {
28558
- const response = await acknowlegdeCardRepo({ ...params });
29383
+ const response = await getAccessManagementSettingsRepo({ ...params });
29384
+ return response;
29385
+ } catch (err) {
29386
+ throw new Error(err.message);
29387
+ }
29388
+ };
29389
+ const convertBufferFile = async (bufferFile) => {
29390
+ return new Promise((resolve, reject) => {
29391
+ const fileStream = Readable.from(bufferFile);
29392
+ let fileBuffer = Buffer.alloc(0);
29393
+ fileStream.on("data", (chunk) => {
29394
+ fileBuffer = Buffer.concat([fileBuffer, chunk]);
29395
+ });
29396
+ fileStream.on("end", () => {
29397
+ try {
29398
+ const workbook = xlsx.read(fileBuffer, { type: "buffer" });
29399
+ const sheetName = workbook.SheetNames[0];
29400
+ const sheet = workbook.Sheets[sheetName];
29401
+ const jsonData = xlsx.utils.sheet_to_json(sheet, { raw: false });
29402
+ resolve(jsonData);
29403
+ } catch (error) {
29404
+ reject("Error parsing file");
29405
+ }
29406
+ });
29407
+ fileStream.on("error", (err) => {
29408
+ reject("Error Reading File: " + err.message);
29409
+ });
29410
+ });
29411
+ };
29412
+ const bulkPhysicalAccessCardSvc = async (params) => {
29413
+ try {
29414
+ const response = await bulkPhysicalAccessCardRepo({ ...params });
29415
+ return response;
29416
+ } catch (err) {
29417
+ throw new Error(err.message);
29418
+ }
29419
+ };
29420
+ const assignAccessCardToUnitSvc = async (params) => {
29421
+ try {
29422
+ const response = await assignAccessCardToUnitRepo({ ...params });
28559
29423
  return response;
28560
29424
  } catch (err) {
28561
29425
  throw new Error(err.message);
@@ -28567,16 +29431,31 @@ function useAccessManagementSvc() {
28567
29431
  doorAccessLevelsSvc,
28568
29432
  liftAccessLevelsSvc,
28569
29433
  accessGroupsSvc,
29434
+ setCache,
29435
+ getCache,
28570
29436
  accessManagementSettingsSvc,
28571
29437
  allAccessCardsCountsSvc,
28572
29438
  availableAccessCardsSvc,
28573
29439
  userTypeAccessCardsSvc,
28574
29440
  assignedAccessCardsSvc,
28575
- acknowlegdeCardSvc
29441
+ acknowlegdeCardSvc,
29442
+ accessandLiftCardsSvc,
29443
+ replaceCardSvc,
29444
+ updateNFCStatusSvc,
29445
+ doorAndLiftDropdownSvc,
29446
+ cardReplacementSvc,
29447
+ visitorAccessCardsSvc,
29448
+ getCardReplacementSvc,
29449
+ getAccessManagementSettingsSvc,
29450
+ convertBufferFile,
29451
+ bulkPhysicalAccessCardSvc,
29452
+ assignAccessCardToUnitSvc
28576
29453
  };
28577
29454
  }
28578
29455
 
28579
29456
  // src/controllers/access-management.controller.ts
29457
+ import { useCache as useCache48 } from "@7365admin1/node-server-utils";
29458
+ var namespace2 = "cache:acm";
28580
29459
  function useAccessManagementController() {
28581
29460
  const {
28582
29461
  addPhysicalCardSvc,
@@ -28584,12 +29463,25 @@ function useAccessManagementController() {
28584
29463
  doorAccessLevelsSvc,
28585
29464
  liftAccessLevelsSvc,
28586
29465
  accessGroupsSvc,
29466
+ setCache,
29467
+ getCache,
28587
29468
  accessManagementSettingsSvc,
28588
29469
  allAccessCardsCountsSvc,
28589
29470
  availableAccessCardsSvc,
28590
29471
  userTypeAccessCardsSvc,
28591
29472
  assignedAccessCardsSvc,
28592
- acknowlegdeCardSvc
29473
+ acknowlegdeCardSvc,
29474
+ accessandLiftCardsSvc,
29475
+ replaceCardSvc,
29476
+ updateNFCStatusSvc,
29477
+ doorAndLiftDropdownSvc,
29478
+ cardReplacementSvc,
29479
+ visitorAccessCardsSvc,
29480
+ getCardReplacementSvc,
29481
+ getAccessManagementSettingsSvc,
29482
+ convertBufferFile,
29483
+ bulkPhysicalAccessCardSvc,
29484
+ assignAccessCardToUnitSvc
28593
29485
  } = useAccessManagementSvc();
28594
29486
  const addPhysicalCard = async (req, res) => {
28595
29487
  try {
@@ -28661,7 +29553,7 @@ function useAccessManagementController() {
28661
29553
  accessGroup: Joi85.array().items(Joi85.string().required()).required(),
28662
29554
  userType: Joi85.string().required(),
28663
29555
  doorName: Joi85.string().required(),
28664
- liftName: Joi85.string().required(),
29556
+ liftName: Joi85.string().optional().allow("", null),
28665
29557
  unit: Joi85.array().items(Joi85.string()).optional().allow(null),
28666
29558
  startDate: Joi85.date().required(),
28667
29559
  endDate: Joi85.date().required(),
@@ -28780,6 +29672,7 @@ function useAccessManagementController() {
28780
29672
  const allAccessCardsCounts = async (req, res) => {
28781
29673
  try {
28782
29674
  const { site, userType } = req.query;
29675
+ const user = req.cookies?.sid;
28783
29676
  const schema2 = Joi85.object({
28784
29677
  site: Joi85.string().hex().required(),
28785
29678
  userType: Joi85.string().required()
@@ -28788,7 +29681,19 @@ function useAccessManagementController() {
28788
29681
  if (error) {
28789
29682
  throw new Error(`${error.message}`);
28790
29683
  }
29684
+ const key = `${namespace2}:${user}:access-card-counts`;
29685
+ const listKey = `${namespace2}:${user}:list`;
29686
+ const { redis } = useCache48(key);
29687
+ const cachedData = await getCache({ key, redis });
29688
+ if (cachedData) {
29689
+ console.log("\u26A1 Cache hit:", key);
29690
+ redis.expire(key, 60).catch(console.error);
29691
+ redis.lrem(listKey, 0, key).then(() => redis.lpush(listKey, key)).then(() => redis.ltrim(listKey, 0, 9)).catch(console.error);
29692
+ return res.status(200).json({ message: "Success", data: cachedData });
29693
+ }
28791
29694
  const result = await allAccessCardsCountsSvc({ site, userType });
29695
+ await setCache({ key, data: result, ttlSeconds: 60, redis });
29696
+ redis.lrem(listKey, 0, key).then(() => redis.lpush(listKey, key)).then(() => redis.ltrim(listKey, 0, 9)).catch(console.error);
28792
29697
  return res.status(200).json({ message: "Success", data: result });
28793
29698
  } catch (error) {
28794
29699
  return res.status(400).json({
@@ -28892,6 +29797,245 @@ function useAccessManagementController() {
28892
29797
  });
28893
29798
  }
28894
29799
  };
29800
+ const accessandLiftCards = async (req, res) => {
29801
+ try {
29802
+ const {
29803
+ accessLevel = null,
29804
+ liftAccessLevel = null,
29805
+ site,
29806
+ userType,
29807
+ type
29808
+ } = req.query;
29809
+ const schema2 = Joi85.object({
29810
+ accessLevel: Joi85.string().optional().allow("", null),
29811
+ liftAccessLevel: Joi85.string().optional().allow("", null),
29812
+ site: Joi85.string().hex().required(),
29813
+ userType: Joi85.string().valid(...Object.values(EAccessCardUserTypes)).required(),
29814
+ type: Joi85.string().valid(...Object.values(EAccessCardTypes)).required()
29815
+ });
29816
+ const { error } = schema2.validate({ accessLevel, liftAccessLevel, site, userType, type });
29817
+ if (error) {
29818
+ return res.status(400).json({ message: error.message });
29819
+ }
29820
+ const result = await accessandLiftCardsSvc({ accessLevel, liftAccessLevel, site, userType, type });
29821
+ return res.status(200).json({ message: "Success", data: result });
29822
+ } catch (error) {
29823
+ return res.status(500).json({
29824
+ data: null,
29825
+ message: error.message
29826
+ });
29827
+ }
29828
+ };
29829
+ const replaceCard = async (req, res) => {
29830
+ try {
29831
+ const { userId, cardId, site, acm_url } = req.body;
29832
+ const schema2 = Joi85.object({
29833
+ userId: Joi85.string().required(),
29834
+ cardId: Joi85.string().required(),
29835
+ site: Joi85.string().required(),
29836
+ acm_url: Joi85.string().required()
29837
+ });
29838
+ const { error } = schema2.validate({ userId, cardId, site, acm_url });
29839
+ if (error) {
29840
+ return res.status(400).json({ message: error.message });
29841
+ }
29842
+ const result = await replaceCardSvc({ userId, cardId, site, acm_url });
29843
+ return res.status(200).json({ message: "Success", data: result });
29844
+ } catch (error) {
29845
+ return res.status(500).json({
29846
+ data: null,
29847
+ message: error.message
29848
+ });
29849
+ }
29850
+ };
29851
+ const updateNFCStatus = async (req, res) => {
29852
+ try {
29853
+ const { nfcList = [], visitorId } = req.body;
29854
+ const schema2 = Joi85.object({
29855
+ nfcList: Joi85.array().items({
29856
+ _id: Joi85.string().hex().length(24).required(),
29857
+ status: Joi85.string().required(),
29858
+ vmsRemarks: Joi85.string().allow(null, "").optional(),
29859
+ updatedAt: Joi85.date().optional().allow(null, "")
29860
+ }),
29861
+ visitorId: Joi85.string().optional().allow(null, "")
29862
+ });
29863
+ const { error } = schema2.validate({ nfcList, visitorId });
29864
+ if (error) {
29865
+ return res.status(400).json({ message: error.message });
29866
+ }
29867
+ const result = await updateNFCStatusSvc({ nfcList, visitorId });
29868
+ return res.status(200).json({ message: "Success", data: result });
29869
+ } catch (error) {
29870
+ return res.status(500).json({
29871
+ data: null,
29872
+ message: error.message
29873
+ });
29874
+ }
29875
+ };
29876
+ const doorAndLiftDropdown = async (req, res) => {
29877
+ try {
29878
+ const { site, type, userType } = req.query;
29879
+ const schema2 = Joi85.object({
29880
+ site: Joi85.string().hex().required(),
29881
+ type: Joi85.string().required(),
29882
+ userType: Joi85.string().required()
29883
+ });
29884
+ const { error } = schema2.validate({ site, type, userType });
29885
+ if (error) {
29886
+ return res.status(400).json({ message: error.message });
29887
+ }
29888
+ const result = await doorAndLiftDropdownSvc({ site, type, userType });
29889
+ return res.status(200).json({ message: "Success", data: result });
29890
+ } catch (error) {
29891
+ return res.status(500).json({
29892
+ data: null,
29893
+ message: error.message
29894
+ });
29895
+ }
29896
+ };
29897
+ const cardReplacement = async (req, res) => {
29898
+ try {
29899
+ const { cardId, remarks } = req.body;
29900
+ const schema2 = Joi85.object({
29901
+ cardId: Joi85.string().required(),
29902
+ remarks: Joi85.string().optional().allow("", null)
29903
+ });
29904
+ const { error } = schema2.validate({ cardId, remarks });
29905
+ if (error) {
29906
+ return res.status(400).json({ message: error.message });
29907
+ }
29908
+ const result = await cardReplacementSvc({ cardId, remarks });
29909
+ return res.status(200).json({ message: "Success", data: result });
29910
+ } catch (error) {
29911
+ return res.status(500).json({
29912
+ data: null,
29913
+ message: error.message
29914
+ });
29915
+ }
29916
+ };
29917
+ const visitorAccessCards = async (req, res) => {
29918
+ try {
29919
+ const {
29920
+ page = 1,
29921
+ limit = 10,
29922
+ search,
29923
+ type,
29924
+ site
29925
+ } = req.query;
29926
+ const schema2 = Joi85.object({
29927
+ site: Joi85.string().hex().required(),
29928
+ page: Joi85.number().required(),
29929
+ limit: Joi85.number().optional().default(10),
29930
+ type: Joi85.string().required().valid(...Object.values(EAccessCardUserTypes)),
29931
+ search: Joi85.string().optional().allow("", null)
29932
+ });
29933
+ const { error } = schema2.validate({ site, page, limit, type, search });
29934
+ if (error) {
29935
+ return res.status(400).json({ message: error.message });
29936
+ }
29937
+ const result = await visitorAccessCardsSvc({ site, page, limit, type, search });
29938
+ return res.status(200).json({ message: "Success", data: result });
29939
+ } catch (error) {
29940
+ return res.status(500).json({
29941
+ data: null,
29942
+ message: error.message
29943
+ });
29944
+ }
29945
+ };
29946
+ const getCardReplacement = async (req, res) => {
29947
+ try {
29948
+ const site = req.params.site;
29949
+ const {
29950
+ search,
29951
+ statusFilter,
29952
+ dateFrom,
29953
+ dateTo,
29954
+ page = 0,
29955
+ limit = 10
29956
+ } = req.query;
29957
+ const schema2 = Joi85.object({
29958
+ search: Joi85.string().optional().allow("", null),
29959
+ statusFilter: Joi85.string().optional().allow("", null),
29960
+ dateFrom: Joi85.date().optional().allow("", null),
29961
+ dateTo: Joi85.date().optional().allow("", null),
29962
+ page: Joi85.number().optional().default(0),
29963
+ limit: Joi85.number().optional().default(10),
29964
+ site: Joi85.string().hex().required()
29965
+ });
29966
+ const { error } = schema2.validate({ search, statusFilter, dateFrom, dateTo, page, limit, site });
29967
+ if (error) {
29968
+ return res.status(400).json({ message: error.message });
29969
+ }
29970
+ const result = await getCardReplacementSvc({ site, page, limit, search, statusFilter, dateFrom, dateTo });
29971
+ return res.status(200).json({ message: "Success", data: result });
29972
+ } catch (error) {
29973
+ return res.status(500).json({
29974
+ data: null,
29975
+ message: error.message
29976
+ });
29977
+ }
29978
+ };
29979
+ const getAccessManagementSettings = async (req, res) => {
29980
+ try {
29981
+ const { site } = req.params;
29982
+ const schema2 = Joi85.object({
29983
+ site: Joi85.string().hex().required()
29984
+ });
29985
+ const { error } = schema2.validate({ site });
29986
+ if (error) {
29987
+ return res.status(400).json({ message: error.message });
29988
+ }
29989
+ const result = await getAccessManagementSettingsSvc({ site });
29990
+ return res.status(200).json({ message: "Success", data: result });
29991
+ } catch (error) {
29992
+ return res.status(500).json({
29993
+ data: null,
29994
+ message: error.message
29995
+ });
29996
+ }
29997
+ };
29998
+ const bulkPhysicalAccessCard = async (req, res) => {
29999
+ try {
30000
+ const { site } = req.query;
30001
+ if (!req.file)
30002
+ throw new Error("File is required!");
30003
+ const xlsData = await convertBufferFile(req.file.buffer);
30004
+ const dataJson = JSON.stringify(xlsData);
30005
+ const result = await bulkPhysicalAccessCardSvc({ dataJson, site });
30006
+ return res.status(200).json({ message: "Success", data: result });
30007
+ } catch (error) {
30008
+ return res.status(500).json({
30009
+ data: null,
30010
+ message: error.message
30011
+ });
30012
+ }
30013
+ };
30014
+ const assignAccessCardToUnit = async (req, res) => {
30015
+ try {
30016
+ const { units, type, quantity, site, userType, accessLevel, liftAccessLevel } = req.body;
30017
+ const schema2 = Joi85.object({
30018
+ units: Joi85.array().items(Joi85.string().hex()).required(),
30019
+ quantity: Joi85.number().required(),
30020
+ type: Joi85.string().required(),
30021
+ site: Joi85.string().hex().required(),
30022
+ userType: Joi85.string().required(),
30023
+ accessLevel: Joi85.string().optional().allow("", null),
30024
+ liftAccessLevel: Joi85.string().optional().allow("", null)
30025
+ });
30026
+ const { error } = schema2.validate({ units, quantity, type, site, userType, accessLevel, liftAccessLevel });
30027
+ if (error) {
30028
+ return res.status(400).json({ message: error.message });
30029
+ }
30030
+ const result = await assignAccessCardToUnitSvc({ units, quantity, type, site, userType, accessLevel, liftAccessLevel });
30031
+ return res.status(200).json({ message: "Success", data: result });
30032
+ } catch (error) {
30033
+ return res.status(500).json({
30034
+ data: null,
30035
+ message: error.message
30036
+ });
30037
+ }
30038
+ };
28895
30039
  return {
28896
30040
  addPhysicalCard,
28897
30041
  addNonPhysicalCard,
@@ -28903,7 +30047,17 @@ function useAccessManagementController() {
28903
30047
  availableAccessCards,
28904
30048
  userTypeAccessCards,
28905
30049
  assignedAccessCards,
28906
- acknowlegdeCard
30050
+ acknowlegdeCard,
30051
+ accessandLiftCards,
30052
+ replaceCard,
30053
+ updateNFCStatus,
30054
+ doorAndLiftDropdown,
30055
+ cardReplacement,
30056
+ visitorAccessCards,
30057
+ getCardReplacement,
30058
+ getAccessManagementSettings,
30059
+ bulkPhysicalAccessCard,
30060
+ assignAccessCardToUnit
28907
30061
  };
28908
30062
  }
28909
30063
 
@@ -28973,7 +30127,7 @@ import {
28973
30127
  makeCacheKey as makeCacheKey45,
28974
30128
  paginate as paginate39,
28975
30129
  useAtlas as useAtlas75,
28976
- useCache as useCache48
30130
+ useCache as useCache49
28977
30131
  } from "@7365admin1/node-server-utils";
28978
30132
  import { ObjectId as ObjectId85 } from "mongodb";
28979
30133
  function useNfcPatrolTagRepo() {
@@ -28984,8 +30138,8 @@ function useNfcPatrolTagRepo() {
28984
30138
  const namespace_collection = "nfc-patrol-tags";
28985
30139
  const namespace_collection_nfc_patrol_routes = "nfc-patrol-routes";
28986
30140
  const collection = db.collection(namespace_collection);
28987
- const { delNamespace, getCache, setCache } = useCache48(namespace_collection);
28988
- const { delNamespace: delNamespaceNfcPatrolRoutes } = useCache48(
30141
+ const { delNamespace, getCache, setCache } = useCache49(namespace_collection);
30142
+ const { delNamespace: delNamespaceNfcPatrolRoutes } = useCache49(
28989
30143
  namespace_collection_nfc_patrol_routes
28990
30144
  );
28991
30145
  async function createIndexes() {
@@ -29432,7 +30586,7 @@ import {
29432
30586
  NotFoundError as NotFoundError37,
29433
30587
  paginate as paginate40,
29434
30588
  useAtlas as useAtlas77,
29435
- useCache as useCache49
30589
+ useCache as useCache50
29436
30590
  } from "@7365admin1/node-server-utils";
29437
30591
  import { ObjectId as ObjectId87 } from "mongodb";
29438
30592
  function useOccurrenceBookRepo() {
@@ -29464,7 +30618,7 @@ function useOccurrenceBookRepo() {
29464
30618
  }
29465
30619
  const namespace_collection = "occurrence-books";
29466
30620
  const collection = db.collection(namespace_collection);
29467
- const { delNamespace, getCache, setCache } = useCache49(namespace_collection);
30621
+ const { delNamespace, getCache, setCache } = useCache50(namespace_collection);
29468
30622
  async function add(value, session) {
29469
30623
  try {
29470
30624
  value = MOccurrenceBook(value);
@@ -30042,7 +31196,7 @@ import {
30042
31196
  NotFoundError as NotFoundError38,
30043
31197
  paginate as paginate41,
30044
31198
  useAtlas as useAtlas79,
30045
- useCache as useCache50
31199
+ useCache as useCache51
30046
31200
  } from "@7365admin1/node-server-utils";
30047
31201
  import { ObjectId as ObjectId89 } from "mongodb";
30048
31202
  function useBulletinVideoRepo() {
@@ -30061,7 +31215,7 @@ function useBulletinVideoRepo() {
30061
31215
  }
30062
31216
  const namespace_collection = "bulletin-videos";
30063
31217
  const collection = db.collection(namespace_collection);
30064
- const { delNamespace, getCache, setCache } = useCache50(namespace_collection);
31218
+ const { delNamespace, getCache, setCache } = useCache51(namespace_collection);
30065
31219
  async function add(value, session) {
30066
31220
  try {
30067
31221
  value = MBulletinVideo(value);
@@ -30593,7 +31747,7 @@ import {
30593
31747
  InternalServerError as InternalServerError51,
30594
31748
  logger as logger127,
30595
31749
  useAtlas as useAtlas81,
30596
- useCache as useCache51,
31750
+ useCache as useCache52,
30597
31751
  paginate as paginate42,
30598
31752
  makeCacheKey as makeCacheKey48
30599
31753
  } from "@7365admin1/node-server-utils";
@@ -30605,7 +31759,7 @@ function useStatementOfAccountRepo() {
30605
31759
  }
30606
31760
  const namespace_collection = "site.statement-of-accounts";
30607
31761
  const collection = db.collection(namespace_collection);
30608
- const { delNamespace, getCache, setCache } = useCache51(namespace_collection);
31762
+ const { delNamespace, getCache, setCache } = useCache52(namespace_collection);
30609
31763
  async function createTextIndex() {
30610
31764
  try {
30611
31765
  await collection.createIndex({
@@ -31368,7 +32522,7 @@ import {
31368
32522
  NotFoundError as NotFoundError40,
31369
32523
  paginate as paginate43,
31370
32524
  useAtlas as useAtlas83,
31371
- useCache as useCache52
32525
+ useCache as useCache53
31372
32526
  } from "@7365admin1/node-server-utils";
31373
32527
  import { ObjectId as ObjectId93 } from "mongodb";
31374
32528
  function useEntryPassSettingsRepo() {
@@ -31378,7 +32532,7 @@ function useEntryPassSettingsRepo() {
31378
32532
  }
31379
32533
  const namespace_collection = "site.entrypass-settings";
31380
32534
  const collection = db.collection(namespace_collection);
31381
- const { delNamespace, getCache, setCache } = useCache52(namespace_collection);
32535
+ const { delNamespace, getCache, setCache } = useCache53(namespace_collection);
31382
32536
  async function createTextIndex() {
31383
32537
  try {
31384
32538
  await collection.createIndex({
@@ -31940,7 +33094,7 @@ import {
31940
33094
  logger as logger133,
31941
33095
  makeCacheKey as makeCacheKey50,
31942
33096
  useAtlas as useAtlas84,
31943
- useCache as useCache53
33097
+ useCache as useCache54
31944
33098
  } from "@7365admin1/node-server-utils";
31945
33099
  function useDashboardRepo() {
31946
33100
  const db = useAtlas84.getDb();
@@ -31951,7 +33105,7 @@ function useDashboardRepo() {
31951
33105
  const work_order_collection = db.collection("work-orders");
31952
33106
  const visitor_collection = db.collection("visitor.transactions");
31953
33107
  const namespace_collection = "dashboard";
31954
- const { delNamespace, getCache, setCache } = useCache53(namespace_collection);
33108
+ const { delNamespace, getCache, setCache } = useCache54(namespace_collection);
31955
33109
  async function getAll({
31956
33110
  site = ""
31957
33111
  }, session) {
@@ -32115,7 +33269,7 @@ import {
32115
33269
  makeCacheKey as makeCacheKey51,
32116
33270
  paginate as paginate44,
32117
33271
  useAtlas as useAtlas85,
32118
- useCache as useCache54
33272
+ useCache as useCache55
32119
33273
  } from "@7365admin1/node-server-utils";
32120
33274
  import { ObjectId as ObjectId95 } from "mongodb";
32121
33275
  function useNfcPatrolRouteRepo() {
@@ -32125,7 +33279,7 @@ function useNfcPatrolRouteRepo() {
32125
33279
  }
32126
33280
  const namespace_collection = "nfc-patrol-routes";
32127
33281
  const collection = db.collection(namespace_collection);
32128
- const { delNamespace, getCache, setCache } = useCache54(namespace_collection);
33282
+ const { delNamespace, getCache, setCache } = useCache55(namespace_collection);
32129
33283
  async function createIndexes() {
32130
33284
  try {
32131
33285
  await collection.createIndexes([
@@ -32862,7 +34016,7 @@ import {
32862
34016
  NotFoundError as NotFoundError43,
32863
34017
  paginate as paginate45,
32864
34018
  useAtlas as useAtlas87,
32865
- useCache as useCache55
34019
+ useCache as useCache56
32866
34020
  } from "@7365admin1/node-server-utils";
32867
34021
  import { ObjectId as ObjectId97 } from "mongodb";
32868
34022
  function useIncidentReportRepo() {
@@ -32893,7 +34047,7 @@ function useIncidentReportRepo() {
32893
34047
  }
32894
34048
  const namespace_collection = "incident-reports";
32895
34049
  const collection = db.collection(namespace_collection);
32896
- const { delNamespace, getCache, setCache } = useCache55(namespace_collection);
34050
+ const { delNamespace, getCache, setCache } = useCache56(namespace_collection);
32897
34051
  async function add(value, session) {
32898
34052
  try {
32899
34053
  value = MIncidentReport(value);
@@ -33634,7 +34788,7 @@ import {
33634
34788
  makeCacheKey as makeCacheKey53,
33635
34789
  NotFoundError as NotFoundError45,
33636
34790
  useAtlas as useAtlas89,
33637
- useCache as useCache56
34791
+ useCache as useCache57
33638
34792
  } from "@7365admin1/node-server-utils";
33639
34793
  import { ObjectId as ObjectId99 } from "mongodb";
33640
34794
  function useNfcPatrolSettingsRepository() {
@@ -33644,7 +34798,7 @@ function useNfcPatrolSettingsRepository() {
33644
34798
  }
33645
34799
  const namespace_collection = "site.nfc-patrol-settings";
33646
34800
  const collection = db.collection(namespace_collection);
33647
- const { delNamespace, setCache, getCache } = useCache56(namespace_collection);
34801
+ const { delNamespace, setCache, getCache } = useCache57(namespace_collection);
33648
34802
  async function createIndexes() {
33649
34803
  try {
33650
34804
  await collection.createIndexes([{ key: { site: 1 }, unique: true }]);
@@ -33889,7 +35043,7 @@ import {
33889
35043
  NotFoundError as NotFoundError46,
33890
35044
  paginate as paginate46,
33891
35045
  useAtlas as useAtlas91,
33892
- useCache as useCache57
35046
+ useCache as useCache58
33893
35047
  } from "@7365admin1/node-server-utils";
33894
35048
 
33895
35049
  // src/models/occurrence-subject.model.ts
@@ -33966,7 +35120,7 @@ function useOccurrenceSubjectRepo() {
33966
35120
  }
33967
35121
  const namespace_collection = "occurrence-subjects";
33968
35122
  const collection = db.collection(namespace_collection);
33969
- const { delNamespace, getCache, setCache } = useCache57(namespace_collection);
35123
+ const { delNamespace, getCache, setCache } = useCache58(namespace_collection);
33970
35124
  async function add(value, session) {
33971
35125
  try {
33972
35126
  value = MOccurrenceSubject(value);
@@ -34534,7 +35688,7 @@ import {
34534
35688
  NotFoundError as NotFoundError47,
34535
35689
  paginate as paginate47,
34536
35690
  useAtlas as useAtlas93,
34537
- useCache as useCache58
35691
+ useCache as useCache59
34538
35692
  } from "@7365admin1/node-server-utils";
34539
35693
  import { ObjectId as ObjectId103 } from "mongodb";
34540
35694
  function useOnlineFormRepo() {
@@ -34544,7 +35698,7 @@ function useOnlineFormRepo() {
34544
35698
  }
34545
35699
  const namespace_collection = "online-forms";
34546
35700
  const collection = db.collection(namespace_collection);
34547
- const { delNamespace, getCache, setCache } = useCache58(namespace_collection);
35701
+ const { delNamespace, getCache, setCache } = useCache59(namespace_collection);
34548
35702
  async function createTextIndex() {
34549
35703
  try {
34550
35704
  await collection.createIndex({
@@ -34587,16 +35741,26 @@ function useOnlineFormRepo() {
34587
35741
  site = ""
34588
35742
  }) {
34589
35743
  page = page > 0 ? page - 1 : 0;
35744
+ try {
35745
+ site = new ObjectId103(site);
35746
+ } catch (error) {
35747
+ throw new BadRequestError168("Invalid site ID format.");
35748
+ }
34590
35749
  sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
34591
35750
  const cacheOptions = {
34592
35751
  page,
34593
35752
  limit,
34594
35753
  status,
35754
+ site: site?.toString(),
34595
35755
  sort: JSON.stringify(sort)
34596
35756
  };
34597
35757
  const query = {
34598
35758
  ...status ? { $and: [{ status }, { status: { $ne: "deleted" } }] } : { status: { $ne: "deleted" } }
34599
35759
  };
35760
+ if (site) {
35761
+ query.site = site;
35762
+ cacheOptions.site = site;
35763
+ }
34600
35764
  if (search) {
34601
35765
  query.$or = [{ name: { $regex: search, $options: "i" } }];
34602
35766
  cacheOptions.search = search;
@@ -34940,7 +36104,7 @@ function useOnlineFormController() {
34940
36104
  }
34941
36105
  async function deleteOnlineFormById(req, res, next) {
34942
36106
  const validation = Joi106.string().hex().required();
34943
- const _id = req.params.id;
36107
+ const _id = req.query.id;
34944
36108
  const { error } = validation.validate(_id);
34945
36109
  if (error) {
34946
36110
  logger148.log({ level: "error", message: error.message });
@@ -35280,7 +36444,7 @@ import {
35280
36444
  makeCacheKey as makeCacheKey56,
35281
36445
  paginate as paginate48,
35282
36446
  useAtlas as useAtlas95,
35283
- useCache as useCache59
36447
+ useCache as useCache60
35284
36448
  } from "@7365admin1/node-server-utils";
35285
36449
  import { ObjectId as ObjectId105 } from "mongodb";
35286
36450
  function useNfcPatrolLogRepo() {
@@ -35290,7 +36454,7 @@ function useNfcPatrolLogRepo() {
35290
36454
  }
35291
36455
  const namespace_collection = "nfc-patrol-logs";
35292
36456
  const collection = db.collection(namespace_collection);
35293
- const { delNamespace, getCache, setCache } = useCache59(namespace_collection);
36457
+ const { delNamespace, getCache, setCache } = useCache60(namespace_collection);
35294
36458
  async function createIndexes() {
35295
36459
  try {
35296
36460
  await collection.createIndexes([