@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.mjs CHANGED
@@ -3649,6 +3649,51 @@ function useMemberRepo() {
3649
3649
  throw error;
3650
3650
  }
3651
3651
  }
3652
+ async function getByUserIdTypeOrg(user, type, org) {
3653
+ try {
3654
+ user = new ObjectId11(user);
3655
+ } catch {
3656
+ throw new BadRequestError11("Invalid user ID format.");
3657
+ }
3658
+ try {
3659
+ org = new ObjectId11(org);
3660
+ } catch {
3661
+ throw new BadRequestError11("Invalid organization ID format.");
3662
+ }
3663
+ const cacheKey = makeCacheKey6(namespace_collection, {
3664
+ user: user.toString(),
3665
+ type,
3666
+ org: org.toString()
3667
+ });
3668
+ const cachedData = await getCache(cacheKey);
3669
+ if (cachedData) {
3670
+ logger8.info(`Cache hit for key: ${cacheKey}`);
3671
+ return cachedData;
3672
+ }
3673
+ try {
3674
+ const data = await collection.findOne({
3675
+ user,
3676
+ type,
3677
+ org
3678
+ });
3679
+ if (!data) {
3680
+ throw new NotFoundError5("Member not found.");
3681
+ }
3682
+ setCache(cacheKey, data, 15 * 60).then(() => {
3683
+ logger8.info(`Cache set for key: ${cacheKey}`);
3684
+ }).catch((err) => {
3685
+ logger8.error(`Failed to set cache for key: ${cacheKey}`, err);
3686
+ });
3687
+ return data;
3688
+ } catch (error) {
3689
+ if (error instanceof AppError2) {
3690
+ throw error;
3691
+ }
3692
+ throw new InternalServerError6(
3693
+ "Internal server error, failed to retrieve member."
3694
+ );
3695
+ }
3696
+ }
3652
3697
  return {
3653
3698
  createIndex,
3654
3699
  createUniqueIndex,
@@ -3669,7 +3714,8 @@ function useMemberRepo() {
3669
3714
  countUserMembershipById,
3670
3715
  updateRoleById,
3671
3716
  getByRoles,
3672
- updateSiteById
3717
+ updateSiteById,
3718
+ getByUserIdTypeOrg
3673
3719
  };
3674
3720
  }
3675
3721
 
@@ -7933,6 +7979,7 @@ function useMemberController() {
7933
7979
  getAll: _getAll,
7934
7980
  getOrgsByMembership: _getOrgsByMembership,
7935
7981
  getByUserIdType: _getByUserIdType,
7982
+ getByUserIdTypeOrg: _getByUserIdTypeOrg,
7936
7983
  updateMemberStatus: _updateMemberStatus,
7937
7984
  updateStatusByUserId: _updateStatusByUserId,
7938
7985
  updateSiteById: _updateSiteById
@@ -8203,17 +8250,57 @@ function useMemberController() {
8203
8250
  next(error2);
8204
8251
  }
8205
8252
  }
8253
+ async function getByUserIdTypeOrg(req, res, next) {
8254
+ const validation = Joi15.object({
8255
+ id: Joi15.string().hex().required(),
8256
+ type: Joi15.string().required(),
8257
+ org: Joi15.string().hex().required()
8258
+ });
8259
+ const params = {
8260
+ ...req.params,
8261
+ ...req.query
8262
+ };
8263
+ const { error } = validation.validate(params);
8264
+ if (error) {
8265
+ logger21.log({
8266
+ level: "error",
8267
+ message: error.message
8268
+ });
8269
+ next(new BadRequestError30(error.message));
8270
+ return;
8271
+ }
8272
+ const user = req.params.id;
8273
+ const type = req.params.type;
8274
+ const org = req.query.org;
8275
+ try {
8276
+ const data = await _getByUserIdTypeOrg(
8277
+ user,
8278
+ type,
8279
+ org
8280
+ );
8281
+ res.json(data);
8282
+ return;
8283
+ } catch (error2) {
8284
+ logger21.log({
8285
+ level: "error",
8286
+ message: error2.message
8287
+ });
8288
+ next(error2);
8289
+ return;
8290
+ }
8291
+ }
8206
8292
  return {
8207
8293
  createMember,
8208
8294
  getByUserId,
8209
8295
  getByUserIdType,
8210
8296
  getAll,
8297
+ getAllByUser,
8211
8298
  getOrgsByMembership,
8212
8299
  updateMemberStatus,
8213
8300
  updateRoleById,
8214
8301
  createMemberDirect,
8215
8302
  updateSiteById,
8216
- getAllByUser
8303
+ getByUserIdTypeOrg
8217
8304
  };
8218
8305
  }
8219
8306
 
@@ -14279,7 +14366,8 @@ function MSiteCamera(value) {
14279
14366
  name: value.name ?? "",
14280
14367
  createdAt: value.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
14281
14368
  updatedAt: value.updatedAt ?? "",
14282
- deletedAt: value.deletedAt ?? ""
14369
+ deletedAt: value.deletedAt ?? "",
14370
+ ANPRSwitches: value.ANPRSwitches ?? void 0
14283
14371
  };
14284
14372
  }
14285
14373
 
@@ -15276,6 +15364,7 @@ var VehicleSort = /* @__PURE__ */ ((VehicleSort2) => {
15276
15364
  var OrgNature = /* @__PURE__ */ ((OrgNature2) => {
15277
15365
  OrgNature2["PROPERTY_MANAGEMENT_AGENCY"] = "property_management_agency";
15278
15366
  OrgNature2["SECURITY_AGENCY"] = "security_agency";
15367
+ OrgNature2["REAL_ESTATE_DEVELOPER"] = "real_estate_developer";
15279
15368
  return OrgNature2;
15280
15369
  })(OrgNature || {});
15281
15370
  var ANPRMode = /* @__PURE__ */ ((ANPRMode2) => {
@@ -16404,39 +16493,70 @@ function useDahuaService() {
16404
16493
  loggerDahua.error("checkOutBySiteAndPlate catch error: ", error);
16405
16494
  }
16406
16495
  }
16407
- async function addTransaction(plateNumber2, site, cameraType, onDetected2) {
16496
+ async function addTransaction(plateNumber2, site, cameraType, ANPRSwitches, onDetected2) {
16408
16497
  if (!plateNumber2 || !site)
16409
- return;
16410
- const resident = await getVehicleBySiteAndPlateNumber(plateNumber2, camera?.site, "resident", "active");
16498
+ return null;
16411
16499
  let insert = null;
16412
- if (resident?._id && (cameraType == "entry" || cameraType == "residents")) {
16500
+ if (cameraType == "entry") {
16413
16501
  await checkOutBySiteAndPlate(camera.site, plateNumber2);
16414
- insert = await add({
16415
- site,
16416
- plateNumber: plateNumber2,
16417
- name: resident?.name,
16418
- nric: resident?.nric,
16419
- contact: resident?.phoneNumber,
16420
- block: Number(resident?.block),
16421
- level: resident?.level,
16422
- unit: resident?.unit?.toString(),
16423
- unitName: resident?.unitName,
16424
- type: resident?.category,
16425
- status: "registered" /* REGISTERED */
16426
- // expiredAt: resident?.end,
16427
- }, void 0, true);
16428
- loggerDahua.info(`${camera?.siteName}-${camera?.direction}] Resident with plate ${plateNumber2} and transaction ID ${insert?._id}`);
16429
- } else if (!resident?._id && (cameraType == "entry" || cameraType == "visitors")) {
16430
- if (!plateNumber2 || !site)
16431
- return;
16502
+ const resident = await getVehicleBySiteAndPlateNumber(plateNumber2, camera?.site, "resident", "active");
16503
+ if (resident?._id) {
16504
+ insert = await add({
16505
+ site,
16506
+ plateNumber: plateNumber2,
16507
+ name: resident?.name,
16508
+ nric: resident?.nric,
16509
+ contact: resident?.phoneNumber,
16510
+ block: Number(resident?.block),
16511
+ level: resident?.level,
16512
+ unit: resident?.unit?.toString(),
16513
+ unitName: resident?.unitName,
16514
+ type: resident?.category,
16515
+ status: "registered" /* REGISTERED */
16516
+ // expiredAt: resident?.end,
16517
+ }, void 0, true);
16518
+ loggerDahua.info(`${camera?.siteName}-${camera?.direction}] Resident with plate ${plateNumber2} and transaction ID ${insert?._id}`);
16519
+ } else if (ANPRSwitches?.enableUnregistered) {
16520
+ insert = await add({
16521
+ site,
16522
+ plateNumber: plateNumber2,
16523
+ status: "unregistered" /* UNREGISTERED */
16524
+ // expiredAt: resident?.end,
16525
+ }, void 0, true);
16526
+ loggerDahua.info(`${camera?.siteName}-${camera?.direction}] Unregistered vehicle with plate ${plateNumber2} and transaction ID ${insert?._id}`);
16527
+ }
16528
+ } else if (cameraType == "residents") {
16432
16529
  await checkOutBySiteAndPlate(camera.site, plateNumber2);
16433
- insert = await add({
16434
- site,
16435
- plateNumber: plateNumber2,
16436
- status: "unregistered" /* UNREGISTERED */
16437
- // expiredAt: resident?.end,
16438
- }, void 0, true);
16439
- loggerDahua.info(`${camera?.siteName}-${camera?.direction}] Unregistered vehicle with plate ${plateNumber2} and transaction ID ${insert?._id}`);
16530
+ const resident = await getVehicleBySiteAndPlateNumber(plateNumber2, camera?.site, "resident", "active");
16531
+ if (resident?._id) {
16532
+ insert = await add({
16533
+ site,
16534
+ plateNumber: plateNumber2,
16535
+ name: resident?.name,
16536
+ nric: resident?.nric,
16537
+ contact: resident?.phoneNumber,
16538
+ block: Number(resident?.block),
16539
+ level: resident?.level,
16540
+ unit: resident?.unit?.toString(),
16541
+ unitName: resident?.unitName,
16542
+ type: resident?.category,
16543
+ status: "registered" /* REGISTERED */
16544
+ // expiredAt: resident?.end,
16545
+ }, void 0, true);
16546
+ loggerDahua.info(`${camera?.siteName}-${camera?.direction}] Resident with plate ${plateNumber2} and transaction ID ${insert?._id}`);
16547
+ }
16548
+ } else if (cameraType == "visitors" && ANPRSwitches?.enableUnregistered) {
16549
+ await checkOutBySiteAndPlate(camera.site, plateNumber2);
16550
+ const resident = await getVehicleBySiteAndPlateNumber(plateNumber2, camera?.site, "resident", "active");
16551
+ if (!resident?._id) {
16552
+ insert = await add({
16553
+ site,
16554
+ plateNumber: plateNumber2,
16555
+ status: "unregistered" /* UNREGISTERED */
16556
+ // expiredAt: resident?.end,
16557
+ }, void 0, true);
16558
+ loggerDahua.info(`${camera?.siteName}-${camera?.direction}] Unregistered vehicle with plate ${plateNumber2} and transaction ID ${insert?._id}`);
16559
+ }
16440
16560
  }
16441
16561
  if (insert?._id && insert?.site && onDetected2) {
16442
16562
  onDetected2({ _id: insert?._id, site: insert?.site?.toString(), plateNumber: insert?.plateNumber, cameraDirection: camera?.direction, direction });
@@ -16449,10 +16569,12 @@ function useDahuaService() {
16449
16569
  );
16450
16570
  if ((camera?.direction == "entry" || camera?.direction == "visitors" || camera?.direction == "residents") && plateNumber) {
16451
16571
  try {
16452
- const result = await addTransaction(plateNumber, camera?.site, camera?.direction, onDetected2);
16453
- const transactionId = result?._id;
16454
- currentTransactionId = transactionId?.toString();
16455
- currentSnapshotField = "snapshotEntryImage";
16572
+ const result = await addTransaction(plateNumber, camera?.site, camera?.direction, camera?.ANPRSwitches, onDetected2);
16573
+ if (camera?.ANPRSwitches?.vehicleSnapshot && result?._id) {
16574
+ const transactionId = result?._id;
16575
+ currentTransactionId = transactionId?.toString();
16576
+ currentSnapshotField = "snapshotEntryImage";
16577
+ }
16456
16578
  } catch (error) {
16457
16579
  console.log("failed to create visitor transaction", error);
16458
16580
  loggerDahua.error(
@@ -16462,23 +16584,25 @@ function useDahuaService() {
16462
16584
  }
16463
16585
  } else if (camera?.direction == "exit" && plateNumber) {
16464
16586
  const existingOpenTransaction = await checkOutBySiteAndPlate(camera?.site, plateNumber, onDetected2);
16465
- if (existingOpenTransaction?._id) {
16587
+ if (existingOpenTransaction?._id && camera?.ANPRSwitches?.vehicleSnapshot) {
16466
16588
  currentTransactionId = existingOpenTransaction._id.toString();
16467
16589
  currentSnapshotField = "snapshotExitImage";
16468
16590
  }
16469
16591
  } else if (camera?.direction == "both" && plateNumber) {
16470
16592
  if (direction.toLowerCase() === "leave") {
16471
16593
  const existingOpenTransaction = await checkOutBySiteAndPlate(camera?.site, plateNumber, onDetected2);
16472
- if (existingOpenTransaction?._id) {
16594
+ if (existingOpenTransaction?._id && camera?.ANPRSwitches?.vehicleSnapshot) {
16473
16595
  currentTransactionId = existingOpenTransaction._id.toString();
16474
16596
  currentSnapshotField = "snapshotExitImage";
16475
16597
  }
16476
16598
  } else if (direction.toLowerCase() === "approach") {
16477
16599
  try {
16478
- const result = await addTransaction(plateNumber, camera?.site, "entry", onDetected2);
16479
- const transactionId = result?._id;
16480
- currentTransactionId = transactionId?.toString();
16481
- currentSnapshotField = "snapshotEntryImage";
16600
+ const result = await addTransaction(plateNumber, camera?.site, "entry", camera?.ANPRSwitches, onDetected2);
16601
+ if (camera?.ANPRSwitches?.vehicleSnapshot && result?._id) {
16602
+ const transactionId = result?._id;
16603
+ currentTransactionId = transactionId?.toString();
16604
+ currentSnapshotField = "snapshotEntryImage";
16605
+ }
16482
16606
  } catch (error) {
16483
16607
  console.log("failed to create visitor transaction", error);
16484
16608
  loggerDahua.error(
@@ -16517,7 +16641,7 @@ function useDahuaService() {
16517
16641
  if (plateNumber && UTCData) {
16518
16642
  await processVehicleTransaction(onDetected2);
16519
16643
  }
16520
- } else if (part.includes("Content-Type: image/jpeg")) {
16644
+ } else if (part.includes("Content-Type: image/jpeg") && camera?.ANPRSwitches?.vehicleSnapshot) {
16521
16645
  const [headers, ...imageParts] = part.split("\r\n\r\n");
16522
16646
  const imageChunk = Buffer.from(imageParts.join("\r\n\r\n"), "binary");
16523
16647
  const lengthMatch = headers.match(/Content-Length:\s*(\d+)/i);
@@ -17332,6 +17456,30 @@ function useSiteCameraRepo() {
17332
17456
  $project: {
17333
17457
  siteDetails: 0
17334
17458
  }
17459
+ },
17460
+ {
17461
+ $lookup: {
17462
+ from: "anpr-settings",
17463
+ localField: "site",
17464
+ foreignField: "site",
17465
+ as: "anprSettingsDetails"
17466
+ }
17467
+ },
17468
+ {
17469
+ $unwind: {
17470
+ path: "$anprSettingsDetails",
17471
+ preserveNullAndEmptyArrays: true
17472
+ }
17473
+ },
17474
+ {
17475
+ $addFields: {
17476
+ ANPRSwitches: "$anprSettingsDetails.ANPRSwitches"
17477
+ }
17478
+ },
17479
+ {
17480
+ $project: {
17481
+ anprSettingsDetails: 0
17482
+ }
17335
17483
  }
17336
17484
  ]).toArray();
17337
17485
  const length = await collection.countDocuments(query);
@@ -17367,9 +17515,29 @@ function useSiteCameraRepo() {
17367
17515
  $addFields: {
17368
17516
  siteName: "$siteDetails.name"
17369
17517
  }
17518
+ },
17519
+ {
17520
+ $lookup: {
17521
+ from: "anpr-settings",
17522
+ localField: "site",
17523
+ foreignField: "site",
17524
+ as: "anprSettingsDetails"
17525
+ }
17526
+ },
17527
+ {
17528
+ $unwind: {
17529
+ path: "$anprSettingsDetails",
17530
+ preserveNullAndEmptyArrays: true
17531
+ }
17532
+ },
17533
+ {
17534
+ $addFields: {
17535
+ ANPRSwitches: "$anprSettingsDetails.ANPRSwitches"
17536
+ }
17370
17537
  }
17371
17538
  ];
17372
17539
  pipeline.push({ $project: { siteDetails: 0 } });
17540
+ pipeline.push({ $project: { anprSettingsDetails: 0 } });
17373
17541
  if (Object.keys(project).length > 0) {
17374
17542
  pipeline.push({ $project: project });
17375
17543
  }
@@ -17380,6 +17548,62 @@ function useSiteCameraRepo() {
17380
17548
  throw error;
17381
17549
  }
17382
17550
  }
17551
+ async function findMany(query, project = {}) {
17552
+ try {
17553
+ const pipeline = [
17554
+ { $match: query },
17555
+ { $limit: 1 },
17556
+ {
17557
+ $lookup: {
17558
+ from: "sites",
17559
+ localField: "site",
17560
+ foreignField: "_id",
17561
+ as: "siteDetails"
17562
+ }
17563
+ },
17564
+ {
17565
+ $unwind: {
17566
+ path: "$siteDetails",
17567
+ preserveNullAndEmptyArrays: true
17568
+ }
17569
+ },
17570
+ {
17571
+ $addFields: {
17572
+ siteName: "$siteDetails.name"
17573
+ }
17574
+ },
17575
+ {
17576
+ $lookup: {
17577
+ from: "anpr-settings",
17578
+ localField: "site",
17579
+ foreignField: "site",
17580
+ as: "anprSettingsDetails"
17581
+ }
17582
+ },
17583
+ {
17584
+ $unwind: {
17585
+ path: "$anprSettingsDetails",
17586
+ preserveNullAndEmptyArrays: true
17587
+ }
17588
+ },
17589
+ {
17590
+ $addFields: {
17591
+ ANPRSwitches: "$anprSettingsDetails.ANPRSwitches"
17592
+ }
17593
+ }
17594
+ ];
17595
+ pipeline.push({ $project: { siteDetails: 0 } });
17596
+ pipeline.push({ $project: { anprSettingsDetails: 0 } });
17597
+ if (Object.keys(project).length > 0) {
17598
+ pipeline.push({ $project: project });
17599
+ }
17600
+ const result = await collection.aggregate(pipeline).toArray();
17601
+ return result.length > 0 ? result : [];
17602
+ } catch (error) {
17603
+ console.error("Error in findOne aggregation:", error);
17604
+ throw error;
17605
+ }
17606
+ }
17383
17607
  return {
17384
17608
  createIndexes,
17385
17609
  add,
@@ -39380,6 +39604,32 @@ function UseAccessManagementRepo() {
39380
39604
  throw new Error(error.message);
39381
39605
  }
39382
39606
  }
39607
+ async function qrCodeListRepo({ type, search, site, page, limit, isLift, userId }) {
39608
+ try {
39609
+ page = page ? page - 1 : 0;
39610
+ let defaultQuery = {};
39611
+ let searchQuery = {};
39612
+ site = new ObjectId92(site);
39613
+ userId = new ObjectId92(userId);
39614
+ if (search) {
39615
+ searchQuery = {
39616
+ $or: [{ fullName: { $regex: search, $options: "i" } }, { cardNo: { $regex: search, $options: "i" } }]
39617
+ };
39618
+ }
39619
+ defaultQuery = { site, isLiftCard: isLift, userId, userType: { $in: ["Visitor/Resident", "Resident/Tenant"] } };
39620
+ const result = collection().aggregate([
39621
+ {
39622
+ $match: { ...defaultQuery, ...searchQuery }
39623
+ },
39624
+ { $sort: { _id: -1 } },
39625
+ { $skip: page * limit },
39626
+ { $limit: limit }
39627
+ ]).toArray();
39628
+ return result;
39629
+ } catch (error) {
39630
+ throw new Error(error.message);
39631
+ }
39632
+ }
39383
39633
  return {
39384
39634
  createIndexes,
39385
39635
  createIndexForEntrypass,
@@ -39418,7 +39668,8 @@ function UseAccessManagementRepo() {
39418
39668
  uploadTemplateRepo,
39419
39669
  getResidentsRepo,
39420
39670
  userAccessCardsRepo,
39421
- removeTemplateRepo
39671
+ removeTemplateRepo,
39672
+ qrCodeListRepo
39422
39673
  };
39423
39674
  }
39424
39675
 
@@ -39465,7 +39716,8 @@ function useAccessManagementSvc() {
39465
39716
  uploadTemplateRepo,
39466
39717
  getResidentsRepo,
39467
39718
  userAccessCardsRepo,
39468
- removeTemplateRepo
39719
+ removeTemplateRepo,
39720
+ qrCodeListRepo
39469
39721
  } = UseAccessManagementRepo();
39470
39722
  const addPhysicalCardSvc = async (payload) => {
39471
39723
  try {
@@ -39851,6 +40103,14 @@ function useAccessManagementSvc() {
39851
40103
  throw new Error(err.message);
39852
40104
  }
39853
40105
  };
40106
+ const qrCodeListSvc = async ({ type, search, site, page, limit, isLift, userId }) => {
40107
+ try {
40108
+ const response = await qrCodeListRepo({ type, search, site, page, limit, isLift, userId });
40109
+ return response;
40110
+ } catch (err) {
40111
+ throw new Error(err.message);
40112
+ }
40113
+ };
39854
40114
  return {
39855
40115
  addPhysicalCardSvc,
39856
40116
  addNonPhysicalCardSvc,
@@ -39892,7 +40152,8 @@ function useAccessManagementSvc() {
39892
40152
  uploadTemplateSvc,
39893
40153
  getResidentsSvc,
39894
40154
  userAccessCardsSvc,
39895
- removeTemplateSvc
40155
+ removeTemplateSvc,
40156
+ qrCodeListSvc
39896
40157
  };
39897
40158
  }
39898
40159
 
@@ -39939,7 +40200,8 @@ function useAccessManagementController() {
39939
40200
  uploadTemplateSvc,
39940
40201
  getResidentsSvc,
39941
40202
  userAccessCardsSvc,
39942
- removeTemplateSvc
40203
+ removeTemplateSvc,
40204
+ qrCodeListSvc
39943
40205
  } = useAccessManagementSvc();
39944
40206
  const addPhysicalCard = async (req, res) => {
39945
40207
  try {
@@ -41008,6 +41270,47 @@ function useAccessManagementController() {
41008
41270
  });
41009
41271
  }
41010
41272
  };
41273
+ const qrCodeList = async (req, res) => {
41274
+ try {
41275
+ const {
41276
+ type,
41277
+ site,
41278
+ page,
41279
+ limit = 10,
41280
+ search = "",
41281
+ isLift,
41282
+ userId
41283
+ } = req.query;
41284
+ const schema2 = Joi87.object({
41285
+ type: Joi87.string().required(),
41286
+ site: Joi87.string().hex().required(),
41287
+ page: Joi87.number().optional().default(1),
41288
+ limit: Joi87.number().optional().default(10),
41289
+ search: Joi87.string().optional().allow("", null),
41290
+ isLift: Joi87.boolean().optional().default(false),
41291
+ userId: Joi87.string().required()
41292
+ });
41293
+ const { error } = schema2.validate({ type, site, page, limit, search, isLift, userId });
41294
+ if (error) {
41295
+ return res.status(400).json({ message: error.message });
41296
+ }
41297
+ const result = await qrCodeListSvc({
41298
+ type,
41299
+ site,
41300
+ page: Number(page),
41301
+ limit: Number(limit),
41302
+ search,
41303
+ isLift: Boolean(isLift),
41304
+ userId
41305
+ });
41306
+ return res.status(200).json({ data: result });
41307
+ } catch (error) {
41308
+ return res.status(400).json({
41309
+ data: null,
41310
+ message: error.message
41311
+ });
41312
+ }
41313
+ };
41011
41314
  return {
41012
41315
  addPhysicalCard,
41013
41316
  addNonPhysicalCard,
@@ -41047,7 +41350,8 @@ function useAccessManagementController() {
41047
41350
  uploadTemplate,
41048
41351
  getResidents,
41049
41352
  userAccessCards,
41050
- removeTemplate
41353
+ removeTemplate,
41354
+ qrCodeList
41051
41355
  };
41052
41356
  }
41053
41357
 
@@ -55538,7 +55842,8 @@ function usePostPrelovedRepo() {
55538
55842
  site,
55539
55843
  status,
55540
55844
  category,
55541
- subcategory
55845
+ subcategory,
55846
+ userId
55542
55847
  }, session) {
55543
55848
  page = page > 0 ? page - 1 : 0;
55544
55849
  if (site) {
@@ -55581,7 +55886,34 @@ function usePostPrelovedRepo() {
55581
55886
  ...categoryId && { category: categoryId },
55582
55887
  ...subcategoryIds && { subcategory: { $in: subcategoryIds } }
55583
55888
  };
55889
+ let userObjectId = null;
55890
+ if (userId) {
55891
+ try {
55892
+ userObjectId = new ObjectId132(userId);
55893
+ } catch {
55894
+ throw new BadRequestError212("Invalid user ID format.");
55895
+ }
55896
+ }
55584
55897
  const sortObj = buildSortObj(filter);
55898
+ const FAVORITE_COUNT_LOOKUP = {
55899
+ $lookup: {
55900
+ from: "post-favorites",
55901
+ localField: "_id",
55902
+ foreignField: "postId",
55903
+ pipeline: [{ $project: { userIds: 1 } }],
55904
+ as: "favoriteData"
55905
+ }
55906
+ };
55907
+ const favoriteUserIds = {
55908
+ $ifNull: [{ $arrayElemAt: ["$favoriteData.userIds", 0] }, []]
55909
+ };
55910
+ const FAVORITE_COUNT_ADD_FIELD = {
55911
+ $addFields: {
55912
+ favoriteCount: { $size: favoriteUserIds },
55913
+ isFavorited: userObjectId ? { $in: [userObjectId, favoriteUserIds] } : false
55914
+ }
55915
+ };
55916
+ const FAVORITE_COUNT_UNSET = { $unset: "favoriteData" };
55585
55917
  try {
55586
55918
  const items = await collection.aggregate(
55587
55919
  [
@@ -55589,6 +55921,9 @@ function usePostPrelovedRepo() {
55589
55921
  USER_LOOKUP,
55590
55922
  USER_UNWIND,
55591
55923
  CATEGORY_LOOKUP,
55924
+ FAVORITE_COUNT_LOOKUP,
55925
+ FAVORITE_COUNT_ADD_FIELD,
55926
+ FAVORITE_COUNT_UNSET,
55592
55927
  { $sort: sortObj },
55593
55928
  { $skip: page * limit },
55594
55929
  { $limit: limit }
@@ -55741,7 +56076,8 @@ function usePostPrelovedController() {
55741
56076
  Joi134.string().valid(...Object.values(PostStatus))
55742
56077
  ).optional().allow(null),
55743
56078
  category: Joi134.string().hex().length(24).optional().allow("", null),
55744
- subcategory: Joi134.alternatives().try(Joi134.array().items(Joi134.string())).optional().allow(null, "")
56079
+ subcategory: Joi134.alternatives().try(Joi134.array().items(Joi134.string())).optional().allow(null, ""),
56080
+ userId: Joi134.string().optional().allow("", null)
55745
56081
  });
55746
56082
  const { error, value } = validation.validate(req.query, {
55747
56083
  abortEarly: false
@@ -55752,7 +56088,17 @@ function usePostPrelovedController() {
55752
56088
  next(new BadRequestError213(messages));
55753
56089
  return;
55754
56090
  }
55755
- const { page, limit, search, filter, site, status, category, subcategory } = value;
56091
+ const {
56092
+ page,
56093
+ limit,
56094
+ search,
56095
+ filter,
56096
+ site,
56097
+ status,
56098
+ category,
56099
+ subcategory,
56100
+ userId
56101
+ } = value;
55756
56102
  try {
55757
56103
  const data = await _getAll({
55758
56104
  page,
@@ -55762,7 +56108,8 @@ function usePostPrelovedController() {
55762
56108
  site,
55763
56109
  status: status ? Array.isArray(status) ? status : [status] : void 0,
55764
56110
  category: category ?? void 0,
55765
- subcategory: subcategory ? Array.isArray(subcategory) ? subcategory : [subcategory] : void 0
56111
+ subcategory: subcategory ? Array.isArray(subcategory) ? subcategory : [subcategory] : void 0,
56112
+ userId
55766
56113
  });
55767
56114
  res.status(200).json(data);
55768
56115
  return;
@@ -56120,7 +56467,7 @@ function MCategoryPreloved(value) {
56120
56467
  name: value.name ?? "",
56121
56468
  createdBy: value.createdBy ?? "",
56122
56469
  site: value.site ?? null,
56123
- createdAt: value.createdAt ?? (/* @__PURE__ */ new Date()).toISOString(),
56470
+ createdAt: value.createdAt ?? /* @__PURE__ */ new Date(),
56124
56471
  updatedAt: value.updatedAt ?? null
56125
56472
  };
56126
56473
  }
@@ -56180,14 +56527,26 @@ function useCategoryPrelovedRepo() {
56180
56527
  throw error;
56181
56528
  }
56182
56529
  }
56183
- return { getAll, getById };
56530
+ async function addCategory(item, session) {
56531
+ const doc = MCategoryPreloved(item);
56532
+ try {
56533
+ const res = await collection.insertOne(doc, { session });
56534
+ return res.insertedId;
56535
+ } catch (error) {
56536
+ const isDuplicated = error.message?.includes("duplicate");
56537
+ if (isDuplicated)
56538
+ throw new BadRequestError216("Category already exists.");
56539
+ throw error;
56540
+ }
56541
+ }
56542
+ return { getAll, getById, addCategory };
56184
56543
  }
56185
56544
 
56186
56545
  // src/controllers/category-preloved.controller.ts
56187
56546
  import { BadRequestError as BadRequestError217, logger as logger190 } from "@7365admin1/node-server-utils";
56188
56547
  import Joi138 from "joi";
56189
56548
  function useCategoryPrelovedController() {
56190
- const { getAll: _getAll, getById: _getById } = useCategoryPrelovedRepo();
56549
+ const { getAll: _getAll, getById: _getById, addCategory: _addCategory } = useCategoryPrelovedRepo();
56191
56550
  async function getAll(req, res, next) {
56192
56551
  const schema2 = Joi138.object({
56193
56552
  search: Joi138.string().optional().allow("", null),
@@ -56230,7 +56589,25 @@ function useCategoryPrelovedController() {
56230
56589
  return;
56231
56590
  }
56232
56591
  }
56233
- return { getAll, getById };
56592
+ async function addCategory(req, res, next) {
56593
+ const { error, value } = schemaCategoryPreloved.validate(req.body, {
56594
+ abortEarly: false
56595
+ });
56596
+ if (error) {
56597
+ const messages = error.details.map((d) => d.message).join(", ");
56598
+ logger190.log({ level: "error", message: messages });
56599
+ next(new BadRequestError217(messages));
56600
+ return;
56601
+ }
56602
+ try {
56603
+ const data = await _addCategory(value);
56604
+ res.status(201).json(data);
56605
+ } catch (error2) {
56606
+ logger190.log({ level: "error", message: error2.message });
56607
+ next(error2);
56608
+ }
56609
+ }
56610
+ return { getAll, getById, addCategory };
56234
56611
  }
56235
56612
 
56236
56613
  // src/models/subcategory-preloved.model.ts