@7365admin1/core 3.30.0 → 3.32.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
@@ -6128,6 +6128,7 @@ __export(src_exports, {
6128
6128
  schemaPostFavorite: () => schemaPostFavorite,
6129
6129
  schemaServiceProvider: () => schemaServiceProvider,
6130
6130
  schemaServiceProviderBilling: () => schemaServiceProviderBilling,
6131
+ schemaSignNfcPatrolLog: () => schemaSignNfcPatrolLog,
6131
6132
  schemaSiteCamera: () => schemaSiteCamera,
6132
6133
  schemaSiteFacility: () => schemaSiteFacility,
6133
6134
  schemaSiteFacilityBooking: () => schemaSiteFacilityBooking,
@@ -36459,7 +36460,6 @@ function usePersonService() {
36459
36460
  }
36460
36461
  return "People added successfully.";
36461
36462
  } catch (error) {
36462
- console.log("error message service", error);
36463
36463
  import_node_server_utils112.logger.error("Error in people service add:", error);
36464
36464
  await session.abortTransaction();
36465
36465
  throw error;
@@ -36616,8 +36616,8 @@ function usePersonService() {
36616
36616
  phoneNumber: person.contact,
36617
36617
  org: person.org.toString(),
36618
36618
  site: person.site.toString(),
36619
- block: person.block ?? void 0,
36620
- level: person.level ?? void 0,
36619
+ block: person.block?.toString() ?? void 0,
36620
+ level: person.level?.toString() ?? void 0,
36621
36621
  unit: person.unit?.toString() ?? void 0,
36622
36622
  nric: person.nric,
36623
36623
  status: "active",
@@ -42372,7 +42372,11 @@ function useBulletinBoardRepo() {
42372
42372
  );
42373
42373
  async function createIndexes() {
42374
42374
  try {
42375
- await collection.createIndexes([{ key: { site: 1, status: 1 } }]);
42375
+ await collection.createIndexes([
42376
+ { key: { site: 1, status: 1, _id: -1 } },
42377
+ { key: { status: 1, startDate: 1 } },
42378
+ { key: { status: 1, endDate: 1 } }
42379
+ ]);
42376
42380
  } catch (error) {
42377
42381
  throw new import_node_server_utils140.InternalServerError("Failed to create index on site.");
42378
42382
  }
@@ -47383,6 +47387,7 @@ function UseAccessManagementRepo() {
47383
47387
  const userType = params.userType;
47384
47388
  const type = params.type;
47385
47389
  const search = params.search;
47390
+ const typeFilter = type.toLowerCase() === "all" ? [] : [{ $eq: ["$type", type] }];
47386
47391
  const query = {
47387
47392
  site: { $in: [site] }
47388
47393
  };
@@ -47409,7 +47414,7 @@ function UseAccessManagementRepo() {
47409
47414
  $lookup: {
47410
47415
  from: "building-levels",
47411
47416
  localField: "_id",
47412
- foreignField: "block",
47417
+ foreignField: "blockId",
47413
47418
  pipeline: [
47414
47419
  { $match: { status: { $ne: "deleted" } } },
47415
47420
  {
@@ -47423,14 +47428,29 @@ function UseAccessManagementRepo() {
47423
47428
  {
47424
47429
  $lookup: {
47425
47430
  from: "access-cards",
47426
- localField: "_id",
47427
- foreignField: "assignedUnit",
47431
+ let: { unit: "$_id" },
47428
47432
  pipeline: [
47429
47433
  {
47430
47434
  $match: {
47431
- isActivated: true,
47432
- userType,
47433
- type
47435
+ $expr: {
47436
+ $and: [
47437
+ {
47438
+ $in: [
47439
+ "$$unit",
47440
+ {
47441
+ $cond: [
47442
+ { $isArray: "$assignedUnit" },
47443
+ "$assignedUnit",
47444
+ ["$assignedUnit"]
47445
+ ]
47446
+ }
47447
+ ]
47448
+ },
47449
+ { $eq: ["$isActivated", true] },
47450
+ { $eq: ["$userType", userType] },
47451
+ ...typeFilter
47452
+ ]
47453
+ }
47434
47454
  }
47435
47455
  },
47436
47456
  {
@@ -47485,7 +47505,7 @@ function UseAccessManagementRepo() {
47485
47505
  {
47486
47506
  $project: {
47487
47507
  _id: 1,
47488
- level: 1,
47508
+ level: "$name",
47489
47509
  units: 1
47490
47510
  }
47491
47511
  }
@@ -47534,10 +47554,11 @@ function UseAccessManagementRepo() {
47534
47554
  },
47535
47555
  {
47536
47556
  $project: {
47537
- name: 1,
47538
- "level.level": 1,
47539
- "level.units.name": 1,
47540
- "level.units.fAccessCards": 1
47557
+ _id: 0,
47558
+ unitId: "$level.units._id",
47559
+ block: "$name",
47560
+ level: "$level.level",
47561
+ unit: "$level.units.name"
47541
47562
  }
47542
47563
  }
47543
47564
  ],
@@ -47548,6 +47569,138 @@ function UseAccessManagementRepo() {
47548
47569
  throw new Error(error.message);
47549
47570
  }
47550
47571
  }
47572
+ async function assignedAccessCardsByUnitRepo(params) {
47573
+ try {
47574
+ const site = new import_mongodb97.ObjectId(params.site);
47575
+ const unitId = new import_mongodb97.ObjectId(params.unitId);
47576
+ const userType = params.userType;
47577
+ const type = params.type;
47578
+ const search = params.search;
47579
+ const typeFilter = type.toLowerCase() === "all" ? [] : [{ $eq: ["$type", type] }];
47580
+ const searchFilter = search ? [
47581
+ {
47582
+ $or: [
47583
+ { cardNo: { $regex: search.trim(), $options: "i" } },
47584
+ { accessLevel: { $regex: search.trim(), $options: "i" } },
47585
+ { doorName: { $regex: search.trim(), $options: "i" } },
47586
+ { liftName: { $regex: search.trim(), $options: "i" } }
47587
+ ]
47588
+ }
47589
+ ] : [];
47590
+ const result = await collectionName("building-units").aggregate(
47591
+ [
47592
+ {
47593
+ $match: {
47594
+ _id: unitId,
47595
+ site,
47596
+ status: { $ne: "deleted" }
47597
+ }
47598
+ },
47599
+ {
47600
+ $lookup: {
47601
+ from: "building-levels",
47602
+ localField: "level",
47603
+ foreignField: "_id",
47604
+ pipeline: [{ $project: { _id: 1, name: 1 } }],
47605
+ as: "levelInfo"
47606
+ }
47607
+ },
47608
+ {
47609
+ $unwind: {
47610
+ path: "$levelInfo",
47611
+ preserveNullAndEmptyArrays: true
47612
+ }
47613
+ },
47614
+ {
47615
+ $lookup: {
47616
+ from: "buildings",
47617
+ localField: "building",
47618
+ foreignField: "_id",
47619
+ pipeline: [{ $project: { _id: 1, name: 1 } }],
47620
+ as: "buildingInfo"
47621
+ }
47622
+ },
47623
+ {
47624
+ $unwind: {
47625
+ path: "$buildingInfo",
47626
+ preserveNullAndEmptyArrays: true
47627
+ }
47628
+ },
47629
+ {
47630
+ $lookup: {
47631
+ from: "access-cards",
47632
+ let: { unit: "$_id" },
47633
+ pipeline: [
47634
+ {
47635
+ $match: {
47636
+ $expr: {
47637
+ $and: [
47638
+ {
47639
+ $in: [
47640
+ "$$unit",
47641
+ {
47642
+ $cond: [
47643
+ { $isArray: "$assignedUnit" },
47644
+ "$assignedUnit",
47645
+ ["$assignedUnit"]
47646
+ ]
47647
+ }
47648
+ ]
47649
+ },
47650
+ { $eq: ["$site", site] },
47651
+ { $eq: ["$isActivated", true] },
47652
+ { $eq: ["$userType", userType] },
47653
+ ...typeFilter
47654
+ ]
47655
+ },
47656
+ ...searchFilter[0]
47657
+ }
47658
+ },
47659
+ { $sort: { _id: -1 } },
47660
+ {
47661
+ $project: {
47662
+ _id: 1,
47663
+ type: 1,
47664
+ cardNo: 1,
47665
+ accessLevel: 1,
47666
+ accessGroup: 1,
47667
+ accessType: 1,
47668
+ qrData: 1,
47669
+ startDate: 1,
47670
+ endDate: 1,
47671
+ isActivated: 1,
47672
+ isAntiPassBack: 1,
47673
+ isLiftCard: 1,
47674
+ liftAccessLevel: 1,
47675
+ doorName: 1,
47676
+ liftName: 1,
47677
+ replacementStatus: 1,
47678
+ qrTag: 1,
47679
+ qrTagCardNo: 1
47680
+ }
47681
+ }
47682
+ ],
47683
+ as: "accessCards"
47684
+ }
47685
+ },
47686
+ {
47687
+ $project: {
47688
+ _id: 0,
47689
+ unitId: "$_id",
47690
+ block: { $ifNull: ["$buildingInfo.name", "$buildingName"] },
47691
+ level: "$levelInfo.name",
47692
+ unit: "$name",
47693
+ accessCards: 1
47694
+ }
47695
+ }
47696
+ ],
47697
+ { allowDiskUse: true }
47698
+ ).toArray();
47699
+ return result[0] ?? null;
47700
+ } catch (error) {
47701
+ throw new Error(error.message);
47702
+ }
47703
+ }
47551
47704
  async function acknowlegdeCardRepo(params) {
47552
47705
  const session = import_node_server_utils158.useAtlas.getClient()?.startSession();
47553
47706
  try {
@@ -49011,7 +49164,8 @@ function UseAccessManagementRepo() {
49011
49164
  assignees,
49012
49165
  unit,
49013
49166
  type,
49014
- acm_url
49167
+ acm_url,
49168
+ id
49015
49169
  }) {
49016
49170
  const session = import_node_server_utils158.useAtlas.getClient()?.startSession();
49017
49171
  try {
@@ -49026,31 +49180,35 @@ function UseAccessManagementRepo() {
49026
49180
  let availableCards = [];
49027
49181
  let update = [];
49028
49182
  let cards = [];
49029
- availableCards = await collection().aggregate([
49030
- {
49031
- $match: {
49032
- $expr: {
49033
- $and: [
49034
- {
49035
- $in: [
49036
- unit,
49037
- {
49038
- $cond: [
49039
- { $isArray: "$assignedUnit" },
49040
- "$assignedUnit",
49041
- ["$assignedUnit"]
49042
- ]
49043
- }
49044
- ]
49045
- },
49046
- { $eq: ["$userId", null] },
49047
- { $eq: ["$type", type] },
49048
- { $eq: ["$isActivated", true] }
49049
- ]
49183
+ if (id) {
49184
+ availableCards = await collection().find({ _id: new import_mongodb97.ObjectId(id) }).toArray();
49185
+ } else {
49186
+ availableCards = await collection().aggregate([
49187
+ {
49188
+ $match: {
49189
+ $expr: {
49190
+ $and: [
49191
+ {
49192
+ $in: [
49193
+ unit,
49194
+ {
49195
+ $cond: [
49196
+ { $isArray: "$assignedUnit" },
49197
+ "$assignedUnit",
49198
+ ["$assignedUnit"]
49199
+ ]
49200
+ }
49201
+ ]
49202
+ },
49203
+ { $eq: ["$userId", null] },
49204
+ { $eq: ["$type", type] },
49205
+ { $eq: ["$isActivated", true] }
49206
+ ]
49207
+ }
49050
49208
  }
49051
49209
  }
49052
- }
49053
- ]).toArray();
49210
+ ]).toArray();
49211
+ }
49054
49212
  if (assignees.length > availableCards.length) {
49055
49213
  throw new Error(`Not enough ${type} cards available.`);
49056
49214
  }
@@ -49106,13 +49264,34 @@ function UseAccessManagementRepo() {
49106
49264
  throw new Error("Command failed, server error.");
49107
49265
  }
49108
49266
  for (const { _id, userId } of update) {
49267
+ const user = userId ? await collectionName("users").findOne(
49268
+ { _id: userId },
49269
+ { projection: { name: 1, email: 1 } }
49270
+ ) : null;
49109
49271
  await collection().updateOne(
49110
49272
  { _id },
49111
49273
  {
49112
- $set: { userId, staffNo: `STAFF-${userId.toString().slice(-10)}` }
49274
+ $set: {
49275
+ userId,
49276
+ staffNo: `STAFF-${userId.toString().slice(-10)}`,
49277
+ userCred: user ? { ...user } : null
49278
+ }
49113
49279
  },
49114
49280
  { session }
49115
49281
  );
49282
+ if (user) {
49283
+ const { _id: userRefId, ...userInfo } = user;
49284
+ await collectionName("access-cards-history").insertOne(
49285
+ {
49286
+ ...userInfo,
49287
+ cardId: _id,
49288
+ userId,
49289
+ createdAt: /* @__PURE__ */ new Date(),
49290
+ type: "assigned"
49291
+ },
49292
+ { session }
49293
+ );
49294
+ }
49116
49295
  }
49117
49296
  await session?.commitTransaction();
49118
49297
  return "Cards assigned successfully.";
@@ -49277,6 +49456,7 @@ function UseAccessManagementRepo() {
49277
49456
  availableAccessCardsRepo,
49278
49457
  userTypeAccessCardsRepo,
49279
49458
  assignedAccessCardsRepo,
49459
+ assignedAccessCardsByUnitRepo,
49280
49460
  acknowlegdeCardRepo,
49281
49461
  accessandLiftCardsRepo,
49282
49462
  replaceCardRepo,
@@ -49328,6 +49508,7 @@ function useAccessManagementSvc() {
49328
49508
  availableAccessCardsRepo,
49329
49509
  userTypeAccessCardsRepo,
49330
49510
  assignedAccessCardsRepo,
49511
+ assignedAccessCardsByUnitRepo,
49331
49512
  acknowlegdeCardRepo,
49332
49513
  accessandLiftCardsRepo,
49333
49514
  replaceCardRepo,
@@ -49502,6 +49683,14 @@ function useAccessManagementSvc() {
49502
49683
  throw new Error(err.message);
49503
49684
  }
49504
49685
  };
49686
+ const assignedAccessCardsByUnitSvc = async (params) => {
49687
+ try {
49688
+ const response = await assignedAccessCardsByUnitRepo({ ...params });
49689
+ return response;
49690
+ } catch (err) {
49691
+ throw new Error(err.message);
49692
+ }
49693
+ };
49505
49694
  const acknowlegdeCardSvc = async (params) => {
49506
49695
  try {
49507
49696
  const response = await acknowlegdeCardRepo({ ...params });
@@ -49717,14 +49906,16 @@ function useAccessManagementSvc() {
49717
49906
  assignees,
49718
49907
  unit,
49719
49908
  type,
49720
- acm_url
49909
+ acm_url,
49910
+ id
49721
49911
  }) => {
49722
49912
  try {
49723
49913
  const response = await assignMultipleCardsRepo({
49724
49914
  assignees,
49725
49915
  unit,
49726
49916
  type,
49727
- acm_url
49917
+ acm_url,
49918
+ id
49728
49919
  });
49729
49920
  return response;
49730
49921
  } catch (err) {
@@ -49818,6 +50009,7 @@ function useAccessManagementSvc() {
49818
50009
  availableAccessCardsSvc,
49819
50010
  userTypeAccessCardsSvc,
49820
50011
  assignedAccessCardsSvc,
50012
+ assignedAccessCardsByUnitSvc,
49821
50013
  acknowlegdeCardSvc,
49822
50014
  accessandLiftCardsSvc,
49823
50015
  replaceCardSvc,
@@ -49867,6 +50059,7 @@ function useAccessManagementController() {
49867
50059
  availableAccessCardsSvc,
49868
50060
  userTypeAccessCardsSvc,
49869
50061
  assignedAccessCardsSvc,
50062
+ assignedAccessCardsByUnitSvc,
49870
50063
  acknowlegdeCardSvc,
49871
50064
  accessandLiftCardsSvc,
49872
50065
  replaceCardSvc,
@@ -50205,6 +50398,47 @@ function useAccessManagementController() {
50205
50398
  });
50206
50399
  }
50207
50400
  };
50401
+ const assignedAccessCardsByUnit = async (req, res) => {
50402
+ try {
50403
+ const {
50404
+ site,
50405
+ unitId,
50406
+ userType,
50407
+ type,
50408
+ search = ""
50409
+ } = req.query;
50410
+ const schema2 = import_joi87.default.object({
50411
+ site: import_joi87.default.string().hex().required(),
50412
+ unitId: import_joi87.default.string().hex().required(),
50413
+ userType: import_joi87.default.string().required(),
50414
+ type: import_joi87.default.string().valid("all", ...Object.values(EAccessCardTypes)).required(),
50415
+ search: import_joi87.default.string().optional().allow("", null)
50416
+ });
50417
+ const { error } = schema2.validate({
50418
+ site,
50419
+ unitId,
50420
+ userType,
50421
+ type,
50422
+ search
50423
+ });
50424
+ if (error) {
50425
+ return res.status(400).json({ message: error.message });
50426
+ }
50427
+ const result = await assignedAccessCardsByUnitSvc({
50428
+ site,
50429
+ unitId,
50430
+ userType,
50431
+ type,
50432
+ search
50433
+ });
50434
+ return res.status(200).json({ message: "Success", data: result });
50435
+ } catch (error) {
50436
+ return res.status(500).json({
50437
+ data: null,
50438
+ message: error.message
50439
+ });
50440
+ }
50441
+ };
50208
50442
  const acknowlegdeCard = async (req, res) => {
50209
50443
  try {
50210
50444
  const { userId, site, cardId } = req.body;
@@ -50849,7 +51083,7 @@ function useAccessManagementController() {
50849
51083
  };
50850
51084
  const assignMultipleCards = async (req, res) => {
50851
51085
  try {
50852
- const { assignees, unit, type, acm_url } = req.body;
51086
+ const { assignees, unit, type, acm_url, id } = req.body;
50853
51087
  const schema2 = import_joi87.default.object({
50854
51088
  assignees: import_joi87.default.array().items(import_joi87.default.string().hex()).required(),
50855
51089
  type: import_joi87.default.string().required(),
@@ -50863,7 +51097,8 @@ function useAccessManagementController() {
50863
51097
  assignees,
50864
51098
  unit,
50865
51099
  type,
50866
- acm_url
51100
+ acm_url,
51101
+ id
50867
51102
  });
50868
51103
  return res.status(200).json({ message: "Success", data: result });
50869
51104
  } catch (error) {
@@ -51044,6 +51279,7 @@ function useAccessManagementController() {
51044
51279
  availableAccessCards,
51045
51280
  userTypeAccessCards,
51046
51281
  assignedAccessCards,
51282
+ assignedAccessCardsByUnit,
51047
51283
  acknowlegdeCard,
51048
51284
  accessandLiftCards,
51049
51285
  replaceCard,
@@ -51464,6 +51700,11 @@ var schemaCreateNfcPatrolLog = import_joi89.default.object({
51464
51700
  startTime: import_joi89.default.string().required(),
51465
51701
  createdBy: import_joi89.default.string().length(24).hex().optional().allow("", null)
51466
51702
  });
51703
+ var schemaSignNfcPatrolLog = import_joi89.default.object({
51704
+ guardName: import_joi89.default.string().required(),
51705
+ guardSignatureFileId: import_joi89.default.string().length(24).hex().required(),
51706
+ signedAt: import_joi89.default.date().optional()
51707
+ });
51467
51708
  var schemaNfcPatrolLog = import_joi89.default.object({
51468
51709
  _id: import_joi89.default.string().length(24).hex().optional().allow(null, ""),
51469
51710
  site: import_joi89.default.string().length(24).hex().required(),
@@ -51502,6 +51743,7 @@ var schemaNfcPatrolLog = import_joi89.default.object({
51502
51743
  skippedRemarks: import_joi89.default.string().required()
51503
51744
  })
51504
51745
  ).min(0).required(),
51746
+ sign: schemaSignNfcPatrolLog.optional(),
51505
51747
  createdBy: import_joi89.default.string().length(24).hex().optional().allow(null, ""),
51506
51748
  createdAt: import_joi89.default.date().optional()
51507
51749
  });
@@ -51537,6 +51779,15 @@ function MNfcPatrolLog(valueArg) {
51537
51779
  throw new import_node_server_utils163.BadRequestError("Invalid route _id format");
51538
51780
  }
51539
51781
  }
51782
+ if (value.sign?.guardSignatureFileId) {
51783
+ try {
51784
+ value.sign.guardSignatureFileId = new import_mongodb100.ObjectId(
51785
+ value.sign.guardSignatureFileId
51786
+ );
51787
+ } catch {
51788
+ throw new import_node_server_utils163.BadRequestError("Invalid guardSignatureFileId format");
51789
+ }
51790
+ }
51540
51791
  return {
51541
51792
  _id: value._id ?? new import_mongodb100.ObjectId(),
51542
51793
  site: value.site,
@@ -51545,6 +51796,7 @@ function MNfcPatrolLog(valueArg) {
51545
51796
  startDateTime: value.startDateTime,
51546
51797
  endDateTime: value.endDateTime,
51547
51798
  checkPoints: value.checkPoints,
51799
+ sign: value.sign,
51548
51800
  createdAt: value.createdAt ?? /* @__PURE__ */ new Date(),
51549
51801
  createdBy: value.createdBy ?? void 0
51550
51802
  };
@@ -52389,25 +52641,13 @@ function useBulletinVideoRepo() {
52389
52641
  }
52390
52642
  async function createIndexes() {
52391
52643
  try {
52392
- await collection.createIndexes([{ key: { site: 1 } }]);
52644
+ await collection.createIndexes([{ key: { site: 1, createdAt: -1 } }]);
52393
52645
  } catch (error) {
52394
52646
  throw new import_node_server_utils168.InternalServerError(
52395
52647
  "Failed to create index on bulletin videos."
52396
52648
  );
52397
52649
  }
52398
52650
  }
52399
- async function createTextIndex() {
52400
- try {
52401
- await collection.createIndex({
52402
- title: "text",
52403
- description: "text"
52404
- });
52405
- } catch (error) {
52406
- throw new import_node_server_utils168.InternalServerError(
52407
- "Failed to create text index on bulletin videos."
52408
- );
52409
- }
52410
- }
52411
52651
  const namespace_collection = "bulletin-videos";
52412
52652
  const collection = db.collection(namespace_collection);
52413
52653
  const { delNamespace, getCache, setCache } = (0, import_node_server_utils168.useCache)(namespace_collection);
@@ -52453,26 +52693,16 @@ function useBulletinVideoRepo() {
52453
52693
  startingDate.setUTCHours(0, 0, 0, 0);
52454
52694
  const endingDate = new Date(endDate);
52455
52695
  endingDate.setUTCHours(23, 59, 59, 999);
52456
- const parsedCreatedAt = {
52457
- $dateFromString: {
52458
- dateString: "$createdAt",
52459
- onError: /* @__PURE__ */ new Date(0),
52460
- onNull: /* @__PURE__ */ new Date(0)
52461
- }
52462
- };
52463
52696
  dateExpr = {
52464
- $expr: {
52465
- $and: [
52466
- { $gte: [parsedCreatedAt, startingDate] },
52467
- { $lte: [parsedCreatedAt, endingDate] }
52468
- ]
52697
+ createdAt: {
52698
+ $gte: startingDate.toISOString(),
52699
+ $lte: endingDate.toISOString()
52469
52700
  }
52470
52701
  };
52471
52702
  }
52472
52703
  const query = {
52473
52704
  site,
52474
52705
  status: { $ne: "deleted" },
52475
- ...search && { $text: { $search: search } },
52476
52706
  ...dateExpr
52477
52707
  };
52478
52708
  sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
@@ -52626,8 +52856,7 @@ function useBulletinVideoRepo() {
52626
52856
  getBulletinVideoById,
52627
52857
  updateBulletinVideoById,
52628
52858
  deleteBulletinVideoById,
52629
- createIndexes,
52630
- createTextIndex
52859
+ createIndexes
52631
52860
  };
52632
52861
  }
52633
52862
 
@@ -52995,8 +53224,8 @@ function useStatementOfAccountRepo() {
52995
53224
  async function createIndexes() {
52996
53225
  try {
52997
53226
  await collection.createIndexes([
52998
- { key: { site: 1, status: 1 } },
52999
- { key: { site: 1, unitId: 1, status: 1 } },
53227
+ { key: { site: 1, status: 1, createdAt: -1 } },
53228
+ { key: { site: 1, unitId: 1, status: 1, createdAt: -1 } },
53000
53229
  { key: { createdAt: -1 } }
53001
53230
  ]);
53002
53231
  return `Successfully created indexes for ${namespace_collection}.`;
@@ -53062,12 +53291,7 @@ function useStatementOfAccountRepo() {
53062
53291
  let endDate = new Date(dateTo);
53063
53292
  endDate.setHours(23, 59, 59, 999);
53064
53293
  dateExpr = {
53065
- $expr: {
53066
- $and: [
53067
- { $gte: ["$createdAt", startDate] },
53068
- { $lte: ["$createdAt", endDate] }
53069
- ]
53070
- }
53294
+ createdAt: { $gte: startDate, $lte: endDate }
53071
53295
  };
53072
53296
  }
53073
53297
  const unitSearchRegex = search ? search.trim().replace(/\s+/g, "").replace(/\//g, "\\s*/\\s*") : null;
@@ -53252,12 +53476,7 @@ function useStatementOfAccountRepo() {
53252
53476
  let endDate = new Date(dateTo);
53253
53477
  endDate.setHours(23, 59, 59, 999);
53254
53478
  dateExpr = {
53255
- $expr: {
53256
- $and: [
53257
- { $gte: ["$createdAt", startDate] },
53258
- { $lte: ["$createdAt", endDate] }
53259
- ]
53260
- }
53479
+ createdAt: { $gte: startDate, $lte: endDate }
53261
53480
  };
53262
53481
  }
53263
53482
  const unitSearchRegex = search ? search.trim().replace(/\s+/g, "").replace(/\//g, "\\s*/\\s*") : null;
@@ -58112,6 +58331,7 @@ function useNfcPatrolLogRepo() {
58112
58331
  limit = 10,
58113
58332
  site,
58114
58333
  date,
58334
+ type,
58115
58335
  route
58116
58336
  }, session) {
58117
58337
  const pageIndex = page > 0 ? page - 1 : 0;
@@ -58125,7 +58345,18 @@ function useNfcPatrolLogRepo() {
58125
58345
  site: siteId
58126
58346
  };
58127
58347
  if (date) {
58128
- query.date = date;
58348
+ if (type === "month") {
58349
+ const [year, month] = date.split("-").map(Number);
58350
+ const endDay = new Date(year, month, 0).getDate();
58351
+ query.date = {
58352
+ $gte: `${year}-${String(month).padStart(2, "0")}-01`,
58353
+ $lte: `${year}-${String(month).padStart(2, "0")}-${String(
58354
+ endDay
58355
+ ).padStart(2, "0")}`
58356
+ };
58357
+ } else {
58358
+ query.date = date;
58359
+ }
58129
58360
  }
58130
58361
  if (route?._id) {
58131
58362
  query["route._id"] = typeof route._id === "string" ? new import_mongodb121.ObjectId(route._id) : route._id;
@@ -58138,13 +58369,17 @@ function useNfcPatrolLogRepo() {
58138
58369
  page: pageIndex,
58139
58370
  limit
58140
58371
  };
58141
- if (date)
58372
+ if (date) {
58142
58373
  cacheOptions.date = date;
58374
+ }
58375
+ if (type) {
58376
+ cacheOptions.type = type;
58377
+ }
58143
58378
  if (route?._id) {
58144
- cacheOptions.routeId = route?._id;
58379
+ cacheOptions.routeId = typeof route._id === "string" ? route._id : route._id.toString();
58145
58380
  }
58146
58381
  if (route?.startTime) {
58147
- cacheOptions.routeStartTime = route?.startTime;
58382
+ cacheOptions.routeStartTime = route.startTime;
58148
58383
  }
58149
58384
  const cacheKey = (0, import_node_server_utils198.makeCacheKey)(namespace_collection, cacheOptions);
58150
58385
  const cachedData = await getCache(cacheKey);
@@ -58152,27 +58387,25 @@ function useNfcPatrolLogRepo() {
58152
58387
  import_node_server_utils198.logger.info(`Cache hit for key: ${cacheKey}`);
58153
58388
  return cachedData;
58154
58389
  }
58155
- try {
58156
- const items = await collection.aggregate(
58157
- [
58158
- { $match: query },
58159
- { $sort: { date: -1 } },
58160
- { $skip: pageIndex * limit },
58161
- { $limit: limit }
58162
- ],
58163
- { session }
58164
- ).toArray();
58165
- const length = await collection.countDocuments(query, { session });
58166
- const data = (0, import_node_server_utils198.paginate)(items, pageIndex, limit, length);
58167
- setCache(cacheKey, data, 15 * 60).then(() => {
58168
- import_node_server_utils198.logger.info(`Cache set for key: ${cacheKey}`);
58169
- }).catch((err) => {
58170
- import_node_server_utils198.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
58171
- });
58172
- return data;
58173
- } catch (error) {
58174
- throw error;
58175
- }
58390
+ const items = await collection.aggregate(
58391
+ [
58392
+ { $match: query },
58393
+ { $sort: { date: -1 } },
58394
+ { $skip: pageIndex * limit },
58395
+ { $limit: limit }
58396
+ ],
58397
+ { session }
58398
+ ).toArray();
58399
+ const length = await collection.countDocuments(query, {
58400
+ session
58401
+ });
58402
+ const data = (0, import_node_server_utils198.paginate)(items, pageIndex, limit, length);
58403
+ setCache(cacheKey, data, 15 * 60).then(() => {
58404
+ import_node_server_utils198.logger.info(`Cache set for key: ${cacheKey}`);
58405
+ }).catch((err) => {
58406
+ import_node_server_utils198.logger.error(`Failed to set cache for key: ${cacheKey}`, err);
58407
+ });
58408
+ return data;
58176
58409
  }
58177
58410
  function delCachedData() {
58178
58411
  delNamespace().then(() => {
@@ -58221,12 +58454,28 @@ function useNfcPatrolLogRepo() {
58221
58454
  delCachedData();
58222
58455
  return res;
58223
58456
  }
58457
+ async function sign(id, value, session) {
58458
+ id = new import_mongodb121.ObjectId(id);
58459
+ await collection.updateOne(
58460
+ { _id: id },
58461
+ {
58462
+ $set: {
58463
+ sign: {
58464
+ ...value,
58465
+ signedAt: /* @__PURE__ */ new Date()
58466
+ }
58467
+ }
58468
+ },
58469
+ { session }
58470
+ );
58471
+ }
58224
58472
  return {
58225
58473
  createIndexes,
58226
58474
  add,
58227
58475
  getAllBySite,
58228
58476
  getById,
58229
- updateCheckpoint
58477
+ updateCheckpoint,
58478
+ sign
58230
58479
  };
58231
58480
  }
58232
58481
 
@@ -58237,7 +58486,8 @@ function useNfcPatrolLogService() {
58237
58486
  add: _add,
58238
58487
  getById,
58239
58488
  updateCheckpoint,
58240
- getAllBySite: _getAllBySite
58489
+ getAllBySite: _getAllBySite,
58490
+ sign: repoSign
58241
58491
  } = useNfcPatrolLogRepo();
58242
58492
  const routeRepo = useNfcPatrolRouteRepo();
58243
58493
  const tagRepo = useNfcPatrolTagRepo();
@@ -58373,9 +58623,26 @@ function useNfcPatrolLogService() {
58373
58623
  await session?.endSession();
58374
58624
  }
58375
58625
  }
58626
+ async function sign(id, value) {
58627
+ const log = await getById(id);
58628
+ if (!log) {
58629
+ throw new import_node_server_utils199.NotFoundError("Patrol log not found.");
58630
+ }
58631
+ const canSign = log.checkPoints.every(
58632
+ (c) => c.status === "Completed" || c.status === "Skipped"
58633
+ );
58634
+ if (!canSign) {
58635
+ throw new import_node_server_utils199.BadRequestError(
58636
+ "All checkpoints must be completed or skipped before signing."
58637
+ );
58638
+ }
58639
+ await repoSign(id, value);
58640
+ return "Successfully signed patrol.";
58641
+ }
58376
58642
  return {
58377
58643
  add,
58378
- completeCheckpoint
58644
+ completeCheckpoint,
58645
+ sign
58379
58646
  };
58380
58647
  }
58381
58648
 
@@ -58383,7 +58650,7 @@ function useNfcPatrolLogService() {
58383
58650
  var import_node_server_utils200 = require("@7365admin1/node-server-utils");
58384
58651
  var import_joi111 = __toESM(require("joi"));
58385
58652
  function useNfcPatrolLogController() {
58386
- const { add: _add, completeCheckpoint: _completeCheckpoint } = useNfcPatrolLogService();
58653
+ const { add: _add, completeCheckpoint: _completeCheckpoint, sign: _sign } = useNfcPatrolLogService();
58387
58654
  const { getAllBySite: _getAllBySite, getById: _getById } = useNfcPatrolLogRepo();
58388
58655
  async function add(req, res, next) {
58389
58656
  try {
@@ -58403,17 +58670,16 @@ function useNfcPatrolLogController() {
58403
58670
  }
58404
58671
  async function getAllBySite(req, res, next) {
58405
58672
  const validation = import_joi111.default.object({
58406
- page: import_joi111.default.number().integer().min(1).allow("", null).default(1),
58407
- limit: import_joi111.default.number().integer().min(1).max(100).allow("", null).default(10),
58673
+ page: import_joi111.default.number().integer().min(1).default(1),
58674
+ limit: import_joi111.default.number().integer().min(1).max(100).default(10),
58408
58675
  site: import_joi111.default.string().length(24).hex().required(),
58409
- date: import_joi111.default.string().regex(/^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/).required().messages({
58410
- "string.pattern.base": "Date must be in YYYY-MM-DD format (e.g., 2025-12-30)"
58411
- }).required(),
58676
+ date: import_joi111.default.string().pattern(/^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12][0-9]|3[01])$/).required().messages({
58677
+ "string.pattern.base": "Date must be in YYYY-MM-DD format (e.g. 2026-07-17)"
58678
+ }),
58679
+ type: import_joi111.default.string().valid("month").optional(),
58412
58680
  route: import_joi111.default.object({
58413
58681
  _id: import_joi111.default.string().length(24).hex().required(),
58414
- startTime: import_joi111.default.string().regex(/^([01]\d|2[0-3]):([0-5]\d)$/).messages({
58415
- "string.pattern.base": "Each startTime must be in HH:mm 24-hour format"
58416
- }).required()
58682
+ startTime: import_joi111.default.string().pattern(/^([01]\d|2[0-3]):([0-5]\d)$/).required()
58417
58683
  }).required()
58418
58684
  });
58419
58685
  const query = {
@@ -58475,11 +58741,26 @@ function useNfcPatrolLogController() {
58475
58741
  next(error);
58476
58742
  }
58477
58743
  }
58744
+ async function sign(req, res, next) {
58745
+ try {
58746
+ const value = await schemaSignNfcPatrolLog.validateAsync(req.body);
58747
+ const result = await _sign(
58748
+ req.params.id,
58749
+ value
58750
+ );
58751
+ res.json({
58752
+ message: result
58753
+ });
58754
+ } catch (err) {
58755
+ next(err);
58756
+ }
58757
+ }
58478
58758
  return {
58479
58759
  add,
58480
58760
  getAllBySite,
58481
58761
  completeCheckpoint,
58482
- getLog
58762
+ getLog,
58763
+ sign
58483
58764
  };
58484
58765
  }
58485
58766
 
@@ -71760,6 +72041,7 @@ function useHidAmicoController() {
71760
72041
  schemaPostFavorite,
71761
72042
  schemaServiceProvider,
71762
72043
  schemaServiceProviderBilling,
72044
+ schemaSignNfcPatrolLog,
71763
72045
  schemaSiteCamera,
71764
72046
  schemaSiteFacility,
71765
72047
  schemaSiteFacilityBooking,