@7365admin1/core 2.71.0 → 2.73.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.js CHANGED
@@ -4088,6 +4088,51 @@ function useMemberRepo() {
4088
4088
  throw error;
4089
4089
  }
4090
4090
  }
4091
+ async function getByUserIdTypeOrg(user, type, org) {
4092
+ try {
4093
+ user = new import_mongodb11.ObjectId(user);
4094
+ } catch {
4095
+ throw new import_node_server_utils12.BadRequestError("Invalid user ID format.");
4096
+ }
4097
+ try {
4098
+ org = new import_mongodb11.ObjectId(org);
4099
+ } catch {
4100
+ throw new import_node_server_utils12.BadRequestError("Invalid organization ID format.");
4101
+ }
4102
+ const cacheKey = (0, import_node_server_utils12.makeCacheKey)(namespace_collection, {
4103
+ user: user.toString(),
4104
+ type,
4105
+ org: org.toString()
4106
+ });
4107
+ const cachedData = await getCache(cacheKey);
4108
+ if (cachedData) {
4109
+ import_node_server_utils12.logger.info(`Cache hit for key: ${cacheKey}`);
4110
+ return cachedData;
4111
+ }
4112
+ try {
4113
+ const data = await collection.findOne({
4114
+ user,
4115
+ type,
4116
+ org
4117
+ });
4118
+ if (!data) {
4119
+ throw new import_node_server_utils12.NotFoundError("Member not found.");
4120
+ }
4121
+ setCache(cacheKey, data, 15 * 60).then(() => {
4122
+ import_node_server_utils12.logger.info(`Cache set for key: ${cacheKey}`);
4123
+ }).catch((err) => {
4124
+ import_node_server_utils12.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
4125
+ });
4126
+ return data;
4127
+ } catch (error) {
4128
+ if (error instanceof import_node_server_utils12.AppError) {
4129
+ throw error;
4130
+ }
4131
+ throw new import_node_server_utils12.InternalServerError(
4132
+ "Internal server error, failed to retrieve member."
4133
+ );
4134
+ }
4135
+ }
4091
4136
  return {
4092
4137
  createIndex,
4093
4138
  createUniqueIndex,
@@ -4108,7 +4153,8 @@ function useMemberRepo() {
4108
4153
  countUserMembershipById,
4109
4154
  updateRoleById,
4110
4155
  getByRoles,
4111
- updateSiteById
4156
+ updateSiteById,
4157
+ getByUserIdTypeOrg
4112
4158
  };
4113
4159
  }
4114
4160
 
@@ -8297,6 +8343,7 @@ function useMemberController() {
8297
8343
  getAll: _getAll,
8298
8344
  getOrgsByMembership: _getOrgsByMembership,
8299
8345
  getByUserIdType: _getByUserIdType,
8346
+ getByUserIdTypeOrg: _getByUserIdTypeOrg,
8300
8347
  updateMemberStatus: _updateMemberStatus,
8301
8348
  updateStatusByUserId: _updateStatusByUserId,
8302
8349
  updateSiteById: _updateSiteById
@@ -8567,17 +8614,57 @@ function useMemberController() {
8567
8614
  next(error2);
8568
8615
  }
8569
8616
  }
8617
+ async function getByUserIdTypeOrg(req, res, next) {
8618
+ const validation = import_joi15.default.object({
8619
+ id: import_joi15.default.string().hex().required(),
8620
+ type: import_joi15.default.string().required(),
8621
+ org: import_joi15.default.string().hex().required()
8622
+ });
8623
+ const params = {
8624
+ ...req.params,
8625
+ ...req.query
8626
+ };
8627
+ const { error } = validation.validate(params);
8628
+ if (error) {
8629
+ import_node_server_utils31.logger.log({
8630
+ level: "error",
8631
+ message: error.message
8632
+ });
8633
+ next(new import_node_server_utils31.BadRequestError(error.message));
8634
+ return;
8635
+ }
8636
+ const user = req.params.id;
8637
+ const type = req.params.type;
8638
+ const org = req.query.org;
8639
+ try {
8640
+ const data = await _getByUserIdTypeOrg(
8641
+ user,
8642
+ type,
8643
+ org
8644
+ );
8645
+ res.json(data);
8646
+ return;
8647
+ } catch (error2) {
8648
+ import_node_server_utils31.logger.log({
8649
+ level: "error",
8650
+ message: error2.message
8651
+ });
8652
+ next(error2);
8653
+ return;
8654
+ }
8655
+ }
8570
8656
  return {
8571
8657
  createMember,
8572
8658
  getByUserId,
8573
8659
  getByUserIdType,
8574
8660
  getAll,
8661
+ getAllByUser,
8575
8662
  getOrgsByMembership,
8576
8663
  updateMemberStatus,
8577
8664
  updateRoleById,
8578
8665
  createMemberDirect,
8579
8666
  updateSiteById,
8580
- getAllByUser
8667
+ getByUserIdTypeOrg
8581
8668
  };
8582
8669
  }
8583
8670
 
@@ -14540,7 +14627,8 @@ function MSiteCamera(value) {
14540
14627
  name: value.name ?? "",
14541
14628
  createdAt: value.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
14542
14629
  updatedAt: value.updatedAt ?? "",
14543
- deletedAt: value.deletedAt ?? ""
14630
+ deletedAt: value.deletedAt ?? "",
14631
+ ANPRSwitches: value.ANPRSwitches ?? void 0
14544
14632
  };
14545
14633
  }
14546
14634
 
@@ -15522,6 +15610,7 @@ var VehicleSort = /* @__PURE__ */ ((VehicleSort2) => {
15522
15610
  var OrgNature = /* @__PURE__ */ ((OrgNature2) => {
15523
15611
  OrgNature2["PROPERTY_MANAGEMENT_AGENCY"] = "property_management_agency";
15524
15612
  OrgNature2["SECURITY_AGENCY"] = "security_agency";
15613
+ OrgNature2["REAL_ESTATE_DEVELOPER"] = "real_estate_developer";
15525
15614
  return OrgNature2;
15526
15615
  })(OrgNature || {});
15527
15616
  var ANPRMode = /* @__PURE__ */ ((ANPRMode2) => {
@@ -16650,39 +16739,70 @@ function useDahuaService() {
16650
16739
  loggerDahua.error("checkOutBySiteAndPlate catch error: ", error);
16651
16740
  }
16652
16741
  }
16653
- async function addTransaction(plateNumber2, site, cameraType, onDetected2) {
16742
+ async function addTransaction(plateNumber2, site, cameraType, ANPRSwitches, onDetected2) {
16654
16743
  if (!plateNumber2 || !site)
16655
- return;
16656
- const resident = await getVehicleBySiteAndPlateNumber(plateNumber2, camera?.site, "resident", "active");
16744
+ return null;
16657
16745
  let insert = null;
16658
- if (resident?._id && (cameraType == "entry" || cameraType == "residents")) {
16746
+ if (cameraType == "entry") {
16659
16747
  await checkOutBySiteAndPlate(camera.site, plateNumber2);
16660
- insert = await add({
16661
- site,
16662
- plateNumber: plateNumber2,
16663
- name: resident?.name,
16664
- nric: resident?.nric,
16665
- contact: resident?.phoneNumber,
16666
- block: Number(resident?.block),
16667
- level: resident?.level,
16668
- unit: resident?.unit?.toString(),
16669
- unitName: resident?.unitName,
16670
- type: resident?.category,
16671
- status: "registered" /* REGISTERED */
16672
- // expiredAt: resident?.end,
16673
- }, void 0, true);
16674
- loggerDahua.info(`${camera?.siteName}-${camera?.direction}] Resident with plate ${plateNumber2} and transaction ID ${insert?._id}`);
16675
- } else if (!resident?._id && (cameraType == "entry" || cameraType == "visitors")) {
16676
- if (!plateNumber2 || !site)
16677
- return;
16748
+ const resident = await getVehicleBySiteAndPlateNumber(plateNumber2, camera?.site, "resident", "active");
16749
+ if (resident?._id) {
16750
+ insert = await add({
16751
+ site,
16752
+ plateNumber: plateNumber2,
16753
+ name: resident?.name,
16754
+ nric: resident?.nric,
16755
+ contact: resident?.phoneNumber,
16756
+ block: Number(resident?.block),
16757
+ level: resident?.level,
16758
+ unit: resident?.unit?.toString(),
16759
+ unitName: resident?.unitName,
16760
+ type: resident?.category,
16761
+ status: "registered" /* REGISTERED */
16762
+ // expiredAt: resident?.end,
16763
+ }, void 0, true);
16764
+ loggerDahua.info(`${camera?.siteName}-${camera?.direction}] Resident with plate ${plateNumber2} and transaction ID ${insert?._id}`);
16765
+ } else if (ANPRSwitches?.enableUnregistered) {
16766
+ insert = await add({
16767
+ site,
16768
+ plateNumber: plateNumber2,
16769
+ status: "unregistered" /* UNREGISTERED */
16770
+ // expiredAt: resident?.end,
16771
+ }, void 0, true);
16772
+ loggerDahua.info(`${camera?.siteName}-${camera?.direction}] Unregistered vehicle with plate ${plateNumber2} and transaction ID ${insert?._id}`);
16773
+ }
16774
+ } else if (cameraType == "residents") {
16678
16775
  await checkOutBySiteAndPlate(camera.site, plateNumber2);
16679
- insert = await add({
16680
- site,
16681
- plateNumber: plateNumber2,
16682
- status: "unregistered" /* UNREGISTERED */
16683
- // expiredAt: resident?.end,
16684
- }, void 0, true);
16685
- loggerDahua.info(`${camera?.siteName}-${camera?.direction}] Unregistered vehicle with plate ${plateNumber2} and transaction ID ${insert?._id}`);
16776
+ const resident = await getVehicleBySiteAndPlateNumber(plateNumber2, camera?.site, "resident", "active");
16777
+ if (resident?._id) {
16778
+ insert = await add({
16779
+ site,
16780
+ plateNumber: plateNumber2,
16781
+ name: resident?.name,
16782
+ nric: resident?.nric,
16783
+ contact: resident?.phoneNumber,
16784
+ block: Number(resident?.block),
16785
+ level: resident?.level,
16786
+ unit: resident?.unit?.toString(),
16787
+ unitName: resident?.unitName,
16788
+ type: resident?.category,
16789
+ status: "registered" /* REGISTERED */
16790
+ // expiredAt: resident?.end,
16791
+ }, void 0, true);
16792
+ loggerDahua.info(`${camera?.siteName}-${camera?.direction}] Resident with plate ${plateNumber2} and transaction ID ${insert?._id}`);
16793
+ }
16794
+ } else if (cameraType == "visitors" && ANPRSwitches?.enableUnregistered) {
16795
+ await checkOutBySiteAndPlate(camera.site, plateNumber2);
16796
+ const resident = await getVehicleBySiteAndPlateNumber(plateNumber2, camera?.site, "resident", "active");
16797
+ if (!resident?._id) {
16798
+ insert = await add({
16799
+ site,
16800
+ plateNumber: plateNumber2,
16801
+ status: "unregistered" /* UNREGISTERED */
16802
+ // expiredAt: resident?.end,
16803
+ }, void 0, true);
16804
+ loggerDahua.info(`${camera?.siteName}-${camera?.direction}] Unregistered vehicle with plate ${plateNumber2} and transaction ID ${insert?._id}`);
16805
+ }
16686
16806
  }
16687
16807
  if (insert?._id && insert?.site && onDetected2) {
16688
16808
  onDetected2({ _id: insert?._id, site: insert?.site?.toString(), plateNumber: insert?.plateNumber, cameraDirection: camera?.direction, direction });
@@ -16695,10 +16815,12 @@ function useDahuaService() {
16695
16815
  );
16696
16816
  if ((camera?.direction == "entry" || camera?.direction == "visitors" || camera?.direction == "residents") && plateNumber) {
16697
16817
  try {
16698
- const result = await addTransaction(plateNumber, camera?.site, camera?.direction, onDetected2);
16699
- const transactionId = result?._id;
16700
- currentTransactionId = transactionId?.toString();
16701
- currentSnapshotField = "snapshotEntryImage";
16818
+ const result = await addTransaction(plateNumber, camera?.site, camera?.direction, camera?.ANPRSwitches, onDetected2);
16819
+ if (camera?.ANPRSwitches?.vehicleSnapshot && result?._id) {
16820
+ const transactionId = result?._id;
16821
+ currentTransactionId = transactionId?.toString();
16822
+ currentSnapshotField = "snapshotEntryImage";
16823
+ }
16702
16824
  } catch (error) {
16703
16825
  console.log("failed to create visitor transaction", error);
16704
16826
  loggerDahua.error(
@@ -16708,23 +16830,25 @@ function useDahuaService() {
16708
16830
  }
16709
16831
  } else if (camera?.direction == "exit" && plateNumber) {
16710
16832
  const existingOpenTransaction = await checkOutBySiteAndPlate(camera?.site, plateNumber, onDetected2);
16711
- if (existingOpenTransaction?._id) {
16833
+ if (existingOpenTransaction?._id && camera?.ANPRSwitches?.vehicleSnapshot) {
16712
16834
  currentTransactionId = existingOpenTransaction._id.toString();
16713
16835
  currentSnapshotField = "snapshotExitImage";
16714
16836
  }
16715
16837
  } else if (camera?.direction == "both" && plateNumber) {
16716
16838
  if (direction.toLowerCase() === "leave") {
16717
16839
  const existingOpenTransaction = await checkOutBySiteAndPlate(camera?.site, plateNumber, onDetected2);
16718
- if (existingOpenTransaction?._id) {
16840
+ if (existingOpenTransaction?._id && camera?.ANPRSwitches?.vehicleSnapshot) {
16719
16841
  currentTransactionId = existingOpenTransaction._id.toString();
16720
16842
  currentSnapshotField = "snapshotExitImage";
16721
16843
  }
16722
16844
  } else if (direction.toLowerCase() === "approach") {
16723
16845
  try {
16724
- const result = await addTransaction(plateNumber, camera?.site, "entry", onDetected2);
16725
- const transactionId = result?._id;
16726
- currentTransactionId = transactionId?.toString();
16727
- currentSnapshotField = "snapshotEntryImage";
16846
+ const result = await addTransaction(plateNumber, camera?.site, "entry", camera?.ANPRSwitches, onDetected2);
16847
+ if (camera?.ANPRSwitches?.vehicleSnapshot && result?._id) {
16848
+ const transactionId = result?._id;
16849
+ currentTransactionId = transactionId?.toString();
16850
+ currentSnapshotField = "snapshotEntryImage";
16851
+ }
16728
16852
  } catch (error) {
16729
16853
  console.log("failed to create visitor transaction", error);
16730
16854
  loggerDahua.error(
@@ -16763,7 +16887,7 @@ function useDahuaService() {
16763
16887
  if (plateNumber && UTCData) {
16764
16888
  await processVehicleTransaction(onDetected2);
16765
16889
  }
16766
- } else if (part.includes("Content-Type: image/jpeg")) {
16890
+ } else if (part.includes("Content-Type: image/jpeg") && camera?.ANPRSwitches?.vehicleSnapshot) {
16767
16891
  const [headers, ...imageParts] = part.split("\r\n\r\n");
16768
16892
  const imageChunk = Buffer.from(imageParts.join("\r\n\r\n"), "binary");
16769
16893
  const lengthMatch = headers.match(/Content-Length:\s*(\d+)/i);
@@ -17578,6 +17702,30 @@ function useSiteCameraRepo() {
17578
17702
  $project: {
17579
17703
  siteDetails: 0
17580
17704
  }
17705
+ },
17706
+ {
17707
+ $lookup: {
17708
+ from: "anpr-settings",
17709
+ localField: "site",
17710
+ foreignField: "site",
17711
+ as: "anprSettingsDetails"
17712
+ }
17713
+ },
17714
+ {
17715
+ $unwind: {
17716
+ path: "$anprSettingsDetails",
17717
+ preserveNullAndEmptyArrays: true
17718
+ }
17719
+ },
17720
+ {
17721
+ $addFields: {
17722
+ ANPRSwitches: "$anprSettingsDetails.ANPRSwitches"
17723
+ }
17724
+ },
17725
+ {
17726
+ $project: {
17727
+ anprSettingsDetails: 0
17728
+ }
17581
17729
  }
17582
17730
  ]).toArray();
17583
17731
  const length = await collection.countDocuments(query);
@@ -17613,9 +17761,29 @@ function useSiteCameraRepo() {
17613
17761
  $addFields: {
17614
17762
  siteName: "$siteDetails.name"
17615
17763
  }
17764
+ },
17765
+ {
17766
+ $lookup: {
17767
+ from: "anpr-settings",
17768
+ localField: "site",
17769
+ foreignField: "site",
17770
+ as: "anprSettingsDetails"
17771
+ }
17772
+ },
17773
+ {
17774
+ $unwind: {
17775
+ path: "$anprSettingsDetails",
17776
+ preserveNullAndEmptyArrays: true
17777
+ }
17778
+ },
17779
+ {
17780
+ $addFields: {
17781
+ ANPRSwitches: "$anprSettingsDetails.ANPRSwitches"
17782
+ }
17616
17783
  }
17617
17784
  ];
17618
17785
  pipeline.push({ $project: { siteDetails: 0 } });
17786
+ pipeline.push({ $project: { anprSettingsDetails: 0 } });
17619
17787
  if (Object.keys(project).length > 0) {
17620
17788
  pipeline.push({ $project: project });
17621
17789
  }
@@ -17626,6 +17794,62 @@ function useSiteCameraRepo() {
17626
17794
  throw error;
17627
17795
  }
17628
17796
  }
17797
+ async function findMany(query, project = {}) {
17798
+ try {
17799
+ const pipeline = [
17800
+ { $match: query },
17801
+ { $limit: 1 },
17802
+ {
17803
+ $lookup: {
17804
+ from: "sites",
17805
+ localField: "site",
17806
+ foreignField: "_id",
17807
+ as: "siteDetails"
17808
+ }
17809
+ },
17810
+ {
17811
+ $unwind: {
17812
+ path: "$siteDetails",
17813
+ preserveNullAndEmptyArrays: true
17814
+ }
17815
+ },
17816
+ {
17817
+ $addFields: {
17818
+ siteName: "$siteDetails.name"
17819
+ }
17820
+ },
17821
+ {
17822
+ $lookup: {
17823
+ from: "anpr-settings",
17824
+ localField: "site",
17825
+ foreignField: "site",
17826
+ as: "anprSettingsDetails"
17827
+ }
17828
+ },
17829
+ {
17830
+ $unwind: {
17831
+ path: "$anprSettingsDetails",
17832
+ preserveNullAndEmptyArrays: true
17833
+ }
17834
+ },
17835
+ {
17836
+ $addFields: {
17837
+ ANPRSwitches: "$anprSettingsDetails.ANPRSwitches"
17838
+ }
17839
+ }
17840
+ ];
17841
+ pipeline.push({ $project: { siteDetails: 0 } });
17842
+ pipeline.push({ $project: { anprSettingsDetails: 0 } });
17843
+ if (Object.keys(project).length > 0) {
17844
+ pipeline.push({ $project: project });
17845
+ }
17846
+ const result = await collection.aggregate(pipeline).toArray();
17847
+ return result.length > 0 ? result : [];
17848
+ } catch (error) {
17849
+ console.error("Error in findOne aggregation:", error);
17850
+ throw error;
17851
+ }
17852
+ }
17629
17853
  return {
17630
17854
  createIndexes,
17631
17855
  add,
@@ -39366,6 +39590,32 @@ function UseAccessManagementRepo() {
39366
39590
  throw new Error(error.message);
39367
39591
  }
39368
39592
  }
39593
+ async function qrCodeListRepo({ type, search, site, page, limit, isLift, userId }) {
39594
+ try {
39595
+ page = page ? page - 1 : 0;
39596
+ let defaultQuery = {};
39597
+ let searchQuery = {};
39598
+ site = new import_mongodb92.ObjectId(site);
39599
+ userId = new import_mongodb92.ObjectId(userId);
39600
+ if (search) {
39601
+ searchQuery = {
39602
+ $or: [{ fullName: { $regex: search, $options: "i" } }, { cardNo: { $regex: search, $options: "i" } }]
39603
+ };
39604
+ }
39605
+ defaultQuery = { site, isLiftCard: isLift, userId, userType: { $in: ["Visitor/Resident", "Resident/Tenant"] } };
39606
+ const result = collection().aggregate([
39607
+ {
39608
+ $match: { ...defaultQuery, ...searchQuery }
39609
+ },
39610
+ { $sort: { _id: -1 } },
39611
+ { $skip: page * limit },
39612
+ { $limit: limit }
39613
+ ]).toArray();
39614
+ return result;
39615
+ } catch (error) {
39616
+ throw new Error(error.message);
39617
+ }
39618
+ }
39369
39619
  return {
39370
39620
  createIndexes,
39371
39621
  createIndexForEntrypass,
@@ -39404,7 +39654,8 @@ function UseAccessManagementRepo() {
39404
39654
  uploadTemplateRepo,
39405
39655
  getResidentsRepo,
39406
39656
  userAccessCardsRepo,
39407
- removeTemplateRepo
39657
+ removeTemplateRepo,
39658
+ qrCodeListRepo
39408
39659
  };
39409
39660
  }
39410
39661
 
@@ -39451,7 +39702,8 @@ function useAccessManagementSvc() {
39451
39702
  uploadTemplateRepo,
39452
39703
  getResidentsRepo,
39453
39704
  userAccessCardsRepo,
39454
- removeTemplateRepo
39705
+ removeTemplateRepo,
39706
+ qrCodeListRepo
39455
39707
  } = UseAccessManagementRepo();
39456
39708
  const addPhysicalCardSvc = async (payload) => {
39457
39709
  try {
@@ -39837,6 +40089,14 @@ function useAccessManagementSvc() {
39837
40089
  throw new Error(err.message);
39838
40090
  }
39839
40091
  };
40092
+ const qrCodeListSvc = async ({ type, search, site, page, limit, isLift, userId }) => {
40093
+ try {
40094
+ const response = await qrCodeListRepo({ type, search, site, page, limit, isLift, userId });
40095
+ return response;
40096
+ } catch (err) {
40097
+ throw new Error(err.message);
40098
+ }
40099
+ };
39840
40100
  return {
39841
40101
  addPhysicalCardSvc,
39842
40102
  addNonPhysicalCardSvc,
@@ -39878,7 +40138,8 @@ function useAccessManagementSvc() {
39878
40138
  uploadTemplateSvc,
39879
40139
  getResidentsSvc,
39880
40140
  userAccessCardsSvc,
39881
- removeTemplateSvc
40141
+ removeTemplateSvc,
40142
+ qrCodeListSvc
39882
40143
  };
39883
40144
  }
39884
40145
 
@@ -39925,7 +40186,8 @@ function useAccessManagementController() {
39925
40186
  uploadTemplateSvc,
39926
40187
  getResidentsSvc,
39927
40188
  userAccessCardsSvc,
39928
- removeTemplateSvc
40189
+ removeTemplateSvc,
40190
+ qrCodeListSvc
39929
40191
  } = useAccessManagementSvc();
39930
40192
  const addPhysicalCard = async (req, res) => {
39931
40193
  try {
@@ -40994,6 +41256,47 @@ function useAccessManagementController() {
40994
41256
  });
40995
41257
  }
40996
41258
  };
41259
+ const qrCodeList = async (req, res) => {
41260
+ try {
41261
+ const {
41262
+ type,
41263
+ site,
41264
+ page,
41265
+ limit = 10,
41266
+ search = "",
41267
+ isLift,
41268
+ userId
41269
+ } = req.query;
41270
+ const schema2 = import_joi87.default.object({
41271
+ type: import_joi87.default.string().required(),
41272
+ site: import_joi87.default.string().hex().required(),
41273
+ page: import_joi87.default.number().optional().default(1),
41274
+ limit: import_joi87.default.number().optional().default(10),
41275
+ search: import_joi87.default.string().optional().allow("", null),
41276
+ isLift: import_joi87.default.boolean().optional().default(false),
41277
+ userId: import_joi87.default.string().required()
41278
+ });
41279
+ const { error } = schema2.validate({ type, site, page, limit, search, isLift, userId });
41280
+ if (error) {
41281
+ return res.status(400).json({ message: error.message });
41282
+ }
41283
+ const result = await qrCodeListSvc({
41284
+ type,
41285
+ site,
41286
+ page: Number(page),
41287
+ limit: Number(limit),
41288
+ search,
41289
+ isLift: Boolean(isLift),
41290
+ userId
41291
+ });
41292
+ return res.status(200).json({ data: result });
41293
+ } catch (error) {
41294
+ return res.status(400).json({
41295
+ data: null,
41296
+ message: error.message
41297
+ });
41298
+ }
41299
+ };
40997
41300
  return {
40998
41301
  addPhysicalCard,
40999
41302
  addNonPhysicalCard,
@@ -41033,7 +41336,8 @@ function useAccessManagementController() {
41033
41336
  uploadTemplate,
41034
41337
  getResidents,
41035
41338
  userAccessCards,
41036
- removeTemplate
41339
+ removeTemplate,
41340
+ qrCodeList
41037
41341
  };
41038
41342
  }
41039
41343
 
@@ -55284,7 +55588,8 @@ function usePostPrelovedRepo() {
55284
55588
  site,
55285
55589
  status,
55286
55590
  category,
55287
- subcategory
55591
+ subcategory,
55592
+ userId
55288
55593
  }, session) {
55289
55594
  page = page > 0 ? page - 1 : 0;
55290
55595
  if (site) {
@@ -55327,7 +55632,34 @@ function usePostPrelovedRepo() {
55327
55632
  ...categoryId && { category: categoryId },
55328
55633
  ...subcategoryIds && { subcategory: { $in: subcategoryIds } }
55329
55634
  };
55635
+ let userObjectId = null;
55636
+ if (userId) {
55637
+ try {
55638
+ userObjectId = new import_mongodb132.ObjectId(userId);
55639
+ } catch {
55640
+ throw new import_node_server_utils235.BadRequestError("Invalid user ID format.");
55641
+ }
55642
+ }
55330
55643
  const sortObj = buildSortObj(filter);
55644
+ const FAVORITE_COUNT_LOOKUP = {
55645
+ $lookup: {
55646
+ from: "post-favorites",
55647
+ localField: "_id",
55648
+ foreignField: "postId",
55649
+ pipeline: [{ $project: { userIds: 1 } }],
55650
+ as: "favoriteData"
55651
+ }
55652
+ };
55653
+ const favoriteUserIds = {
55654
+ $ifNull: [{ $arrayElemAt: ["$favoriteData.userIds", 0] }, []]
55655
+ };
55656
+ const FAVORITE_COUNT_ADD_FIELD = {
55657
+ $addFields: {
55658
+ favoriteCount: { $size: favoriteUserIds },
55659
+ isFavorited: userObjectId ? { $in: [userObjectId, favoriteUserIds] } : false
55660
+ }
55661
+ };
55662
+ const FAVORITE_COUNT_UNSET = { $unset: "favoriteData" };
55331
55663
  try {
55332
55664
  const items = await collection.aggregate(
55333
55665
  [
@@ -55335,6 +55667,9 @@ function usePostPrelovedRepo() {
55335
55667
  USER_LOOKUP,
55336
55668
  USER_UNWIND,
55337
55669
  CATEGORY_LOOKUP,
55670
+ FAVORITE_COUNT_LOOKUP,
55671
+ FAVORITE_COUNT_ADD_FIELD,
55672
+ FAVORITE_COUNT_UNSET,
55338
55673
  { $sort: sortObj },
55339
55674
  { $skip: page * limit },
55340
55675
  { $limit: limit }
@@ -55487,7 +55822,8 @@ function usePostPrelovedController() {
55487
55822
  import_joi134.default.string().valid(...Object.values(PostStatus))
55488
55823
  ).optional().allow(null),
55489
55824
  category: import_joi134.default.string().hex().length(24).optional().allow("", null),
55490
- subcategory: import_joi134.default.alternatives().try(import_joi134.default.array().items(import_joi134.default.string())).optional().allow(null, "")
55825
+ subcategory: import_joi134.default.alternatives().try(import_joi134.default.array().items(import_joi134.default.string())).optional().allow(null, ""),
55826
+ userId: import_joi134.default.string().optional().allow("", null)
55491
55827
  });
55492
55828
  const { error, value } = validation.validate(req.query, {
55493
55829
  abortEarly: false
@@ -55498,7 +55834,17 @@ function usePostPrelovedController() {
55498
55834
  next(new import_node_server_utils236.BadRequestError(messages));
55499
55835
  return;
55500
55836
  }
55501
- const { page, limit, search, filter, site, status, category, subcategory } = value;
55837
+ const {
55838
+ page,
55839
+ limit,
55840
+ search,
55841
+ filter,
55842
+ site,
55843
+ status,
55844
+ category,
55845
+ subcategory,
55846
+ userId
55847
+ } = value;
55502
55848
  try {
55503
55849
  const data = await _getAll({
55504
55850
  page,
@@ -55508,7 +55854,8 @@ function usePostPrelovedController() {
55508
55854
  site,
55509
55855
  status: status ? Array.isArray(status) ? status : [status] : void 0,
55510
55856
  category: category ?? void 0,
55511
- subcategory: subcategory ? Array.isArray(subcategory) ? subcategory : [subcategory] : void 0
55857
+ subcategory: subcategory ? Array.isArray(subcategory) ? subcategory : [subcategory] : void 0,
55858
+ userId
55512
55859
  });
55513
55860
  res.status(200).json(data);
55514
55861
  return;
@@ -55861,7 +56208,7 @@ function MCategoryPreloved(value) {
55861
56208
  name: value.name ?? "",
55862
56209
  createdBy: value.createdBy ?? "",
55863
56210
  site: value.site ?? null,
55864
- createdAt: value.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
56211
+ createdAt: value.createdAt ?? /* @__PURE__ */ new Date(),
55865
56212
  updatedAt: value.updatedAt ?? null
55866
56213
  };
55867
56214
  }
@@ -55916,14 +56263,26 @@ function useCategoryPrelovedRepo() {
55916
56263
  throw error;
55917
56264
  }
55918
56265
  }
55919
- return { getAll, getById };
56266
+ async function addCategory(item, session) {
56267
+ const doc = MCategoryPreloved(item);
56268
+ try {
56269
+ const res = await collection.insertOne(doc, { session });
56270
+ return res.insertedId;
56271
+ } catch (error) {
56272
+ const isDuplicated = error.message?.includes("duplicate");
56273
+ if (isDuplicated)
56274
+ throw new import_node_server_utils240.BadRequestError("Category already exists.");
56275
+ throw error;
56276
+ }
56277
+ }
56278
+ return { getAll, getById, addCategory };
55920
56279
  }
55921
56280
 
55922
56281
  // src/controllers/category-preloved.controller.ts
55923
56282
  var import_node_server_utils241 = require("@7365admin1/node-server-utils");
55924
56283
  var import_joi138 = __toESM(require("joi"));
55925
56284
  function useCategoryPrelovedController() {
55926
- const { getAll: _getAll, getById: _getById } = useCategoryPrelovedRepo();
56285
+ const { getAll: _getAll, getById: _getById, addCategory: _addCategory } = useCategoryPrelovedRepo();
55927
56286
  async function getAll(req, res, next) {
55928
56287
  const schema2 = import_joi138.default.object({
55929
56288
  search: import_joi138.default.string().optional().allow("", null),
@@ -55966,7 +56325,25 @@ function useCategoryPrelovedController() {
55966
56325
  return;
55967
56326
  }
55968
56327
  }
55969
- return { getAll, getById };
56328
+ async function addCategory(req, res, next) {
56329
+ const { error, value } = schemaCategoryPreloved.validate(req.body, {
56330
+ abortEarly: false
56331
+ });
56332
+ if (error) {
56333
+ const messages = error.details.map((d) => d.message).join(", ");
56334
+ import_node_server_utils241.logger.log({ level: "error", message: messages });
56335
+ next(new import_node_server_utils241.BadRequestError(messages));
56336
+ return;
56337
+ }
56338
+ try {
56339
+ const data = await _addCategory(value);
56340
+ res.status(201).json(data);
56341
+ } catch (error2) {
56342
+ import_node_server_utils241.logger.log({ level: "error", message: error2.message });
56343
+ next(error2);
56344
+ }
56345
+ }
56346
+ return { getAll, getById, addCategory };
55970
56347
  }
55971
56348
 
55972
56349
  // src/models/subcategory-preloved.model.ts