@7365admin1/core 3.6.0 → 3.7.1

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
@@ -11889,9 +11889,7 @@ function useVerificationService() {
11889
11889
  ...metadata,
11890
11890
  app
11891
11891
  },
11892
- expireAt: new Date(
11893
- Date.now() + 72 * 60 * 60 * 1e3
11894
- ).toISOString(),
11892
+ expireAt: new Date(Date.now() + 72 * 60 * 60 * 1e3).toISOString(),
11895
11893
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
11896
11894
  };
11897
11895
  const createdId = await add(value);
@@ -11910,10 +11908,7 @@ function useVerificationService() {
11910
11908
  hasPestControl: app === "pest_control_services",
11911
11909
  hasPoolMaintenance: app === "pool_maintenance_services"
11912
11910
  },
11913
- filePath: getDirectory(
11914
- __dirname,
11915
- "./public/handlebars/user-invite"
11916
- )
11911
+ filePath: getDirectory(__dirname, "./public/handlebars/user-invite")
11917
11912
  });
11918
11913
  await mailer.sendMail({
11919
11914
  to: email,
@@ -12056,7 +12051,15 @@ function useVerificationService() {
12056
12051
  throw error2;
12057
12052
  }
12058
12053
  }
12059
- async function createSimpleServiceProviderInvite({ email, app, name, role, orgId, siteId, siteName }) {
12054
+ async function createSimpleServiceProviderInvite({
12055
+ email,
12056
+ app,
12057
+ name,
12058
+ role,
12059
+ orgId,
12060
+ siteId,
12061
+ siteName
12062
+ }) {
12060
12063
  const schema2 = Joi11.object({
12061
12064
  email: Joi11.string().email().lowercase().required(),
12062
12065
  app: Joi11.string().allow("", null),
@@ -12098,7 +12101,10 @@ function useVerificationService() {
12098
12101
  };
12099
12102
  try {
12100
12103
  const id = await _add(value);
12101
- const filePath = getDirectory(__dirname, `./public/handlebars/${value.type}`);
12104
+ const filePath = getDirectory(
12105
+ __dirname,
12106
+ `./public/handlebars/${value.type}`
12107
+ );
12102
12108
  const link = `${APP_MAIN}/verify/${value.type}/${id}`;
12103
12109
  const emailContent = compileHandlebar({
12104
12110
  context: {
@@ -18547,7 +18553,7 @@ function useServiceProviderRepo() {
18547
18553
  }) {
18548
18554
  page = page > 0 ? page - 1 : 0;
18549
18555
  const query = { status };
18550
- const cacheOptions = { status };
18556
+ const cacheOptions = { status, page, limit };
18551
18557
  sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
18552
18558
  cacheOptions.sort = JSON.stringify(sort);
18553
18559
  if (search) {
@@ -21025,6 +21031,15 @@ async function convertObjectIdUtil(id) {
21025
21031
  return Promise.reject("Invalid ID conversion to ObjectId");
21026
21032
  }
21027
21033
  }
21034
+ async function convertObjectIdUtil2(id, fieldName) {
21035
+ try {
21036
+ if (!id)
21037
+ throw new Error(`Invalid ID conversion to ObjectId of ${fieldName}.`);
21038
+ return new ObjectId40(id);
21039
+ } catch (_) {
21040
+ throw new Error(`Invalid ID conversion to ObjectId of ${fieldName}.`);
21041
+ }
21042
+ }
21028
21043
 
21029
21044
  // src/repositories/visitor-transaction.repo.ts
21030
21045
  import moment from "moment-timezone";
@@ -21385,6 +21400,10 @@ function useVisitorTransactionRepo() {
21385
21400
  const data = paginate17(items, page, limit, totalCount);
21386
21401
  return data;
21387
21402
  } catch (error) {
21403
+ logger48.error("Error in getAll visitor transaction repo", {
21404
+ message: error.message,
21405
+ stack: error.stack
21406
+ });
21388
21407
  throw error;
21389
21408
  }
21390
21409
  }
@@ -21457,6 +21476,22 @@ function useVisitorTransactionRepo() {
21457
21476
  ]).toArray();
21458
21477
  return result;
21459
21478
  } catch (error) {
21479
+ if (error instanceof Error) {
21480
+ logger48.error(
21481
+ "Error in getVisitorTransactionById visitor transaction repo",
21482
+ {
21483
+ message: error.message,
21484
+ stack: error.stack
21485
+ }
21486
+ );
21487
+ } else {
21488
+ logger48.error(
21489
+ "Unknown error in getVisitorTransactionById visitor transaction repo",
21490
+ {
21491
+ error
21492
+ }
21493
+ );
21494
+ }
21460
21495
  throw error;
21461
21496
  }
21462
21497
  }
@@ -21471,9 +21506,19 @@ function useVisitorTransactionRepo() {
21471
21506
  const data = await collection.findOne(query);
21472
21507
  return data;
21473
21508
  } catch (error) {
21474
- throw new InternalServerError24(
21475
- "Failed to fetch visitor transaction by plate number."
21476
- );
21509
+ if (error instanceof Error) {
21510
+ logger48.error("Error in getOpenByPlateNumber visitor transaction repo", {
21511
+ message: error.message,
21512
+ stack: error.stack
21513
+ });
21514
+ } else {
21515
+ logger48.error(
21516
+ "Unknown error in getOpenByPlateNumber visitor transaction repo",
21517
+ {
21518
+ error
21519
+ }
21520
+ );
21521
+ }
21477
21522
  }
21478
21523
  }
21479
21524
  async function updateById(_id, value, session, isManualCheckOut = true) {
@@ -22797,6 +22842,38 @@ function useVehicleRepo() {
22797
22842
  throw error;
22798
22843
  }
22799
22844
  }
22845
+ async function getBlocklistedVehicleByPlateNumber(plateNumber, site) {
22846
+ if (!plateNumber) {
22847
+ throw new BadRequestError69("Plate number is required");
22848
+ }
22849
+ const baseQuery = {
22850
+ type: "blocklist" /* BLOCKLIST */,
22851
+ plateNumber,
22852
+ ...site && {
22853
+ site: typeof site === "string" ? new ObjectId43(site) : site
22854
+ }
22855
+ };
22856
+ try {
22857
+ const pipeline = [
22858
+ { $match: baseQuery },
22859
+ {
22860
+ $addFields: {
22861
+ latestDate: { $max: ["$createdAt", "$updatedAt"] }
22862
+ }
22863
+ },
22864
+ { $sort: { latestDate: -1 } },
22865
+ {
22866
+ $project: {
22867
+ latestDate: 0
22868
+ }
22869
+ }
22870
+ ];
22871
+ const [result] = await collection.aggregate(pipeline).toArray();
22872
+ return result;
22873
+ } catch (error) {
22874
+ throw error;
22875
+ }
22876
+ }
22800
22877
  return {
22801
22878
  createIndex,
22802
22879
  createTextIndex,
@@ -22815,7 +22892,8 @@ function useVehicleRepo() {
22815
22892
  bulkUpsertVehicles,
22816
22893
  getSpecificVehicleById,
22817
22894
  getBlocklistedVehicles,
22818
- getVehicleBySiteAndPlateNumber
22895
+ getVehicleBySiteAndPlateNumber,
22896
+ getBlocklistedVehicleByPlateNumber
22819
22897
  };
22820
22898
  }
22821
22899
 
@@ -25762,7 +25840,6 @@ function useBuildingUnitRepo() {
25762
25840
  const buildingCollection = await db?.collection("buildings").findOne({ _id: toObjectId11(block) });
25763
25841
  const blockNumber = buildingCollection?.block;
25764
25842
  query.block = blockNumber !== void 0 ? blockNumber : block;
25765
- console.log("Query for getBuildingUnits:", query);
25766
25843
  try {
25767
25844
  const data = await collection.aggregate([{ $match: query }, { $project: { name: 1 } }]).toArray();
25768
25845
  setCache(cacheKey, data, 15 * 60).then(() => {
@@ -25819,6 +25896,20 @@ function useBuildingUnitRepo() {
25819
25896
  try {
25820
25897
  const data = await collection.aggregate([
25821
25898
  { $match: query },
25899
+ {
25900
+ $lookup: {
25901
+ from: "buildings",
25902
+ localField: "building",
25903
+ foreignField: "_id",
25904
+ pipeline: [{ $project: { _id: 0, name: 1 } }],
25905
+ as: "_blockData"
25906
+ }
25907
+ },
25908
+ {
25909
+ $unwind: { path: "$_blockData", preserveNullAndEmptyArrays: true }
25910
+ },
25911
+ { $addFields: { blockName: { $ifNull: ["$_blockData.name", ""] } } },
25912
+ { $unset: "_blockData" },
25822
25913
  {
25823
25914
  $lookup: {
25824
25915
  from: "building-levels",
@@ -25828,7 +25919,9 @@ function useBuildingUnitRepo() {
25828
25919
  as: "_levelData"
25829
25920
  }
25830
25921
  },
25831
- { $unwind: { path: "$_levelData", preserveNullAndEmptyArrays: true } },
25922
+ {
25923
+ $unwind: { path: "$_levelData", preserveNullAndEmptyArrays: true }
25924
+ },
25832
25925
  { $addFields: { levelName: { $ifNull: ["$_levelData.name", ""] } } },
25833
25926
  { $unset: "_levelData" }
25834
25927
  ]).toArray();
@@ -25934,7 +26027,6 @@ function useBuildingUnitRepo() {
25934
26027
  level,
25935
26028
  status: "active"
25936
26029
  };
25937
- console.log(query);
25938
26030
  const result = await collection.findOne(query);
25939
26031
  setCache(cacheKey, result, 300).then(() => {
25940
26032
  logger54.log({
@@ -33235,6 +33327,71 @@ var KeyRepo = class {
33235
33327
  return Promise.reject("Failed to delete key");
33236
33328
  }
33237
33329
  }
33330
+ static async getById2(id) {
33331
+ return this.collection().aggregate([
33332
+ { $match: { _id: new ObjectId61(id) } },
33333
+ {
33334
+ $lookup: {
33335
+ from: "qr-code-templates",
33336
+ localField: "template",
33337
+ foreignField: "_id",
33338
+ as: "QRTemplateInfo"
33339
+ }
33340
+ },
33341
+ {
33342
+ $unwind: {
33343
+ path: "$QRTemplateInfo",
33344
+ preserveNullAndEmptyArrays: true
33345
+ }
33346
+ },
33347
+ {
33348
+ $addFields: {
33349
+ prefixPass: { $toUpper: "$QRTemplateInfo.prefixPass" },
33350
+ prefixKey: { $toUpper: "$QRTemplateInfo.prefixKey" },
33351
+ templateName: "$QRTemplateInfo.name"
33352
+ }
33353
+ },
33354
+ {
33355
+ $addFields: {
33356
+ prefixAndName: {
33357
+ $cond: {
33358
+ if: { $or: [{ $not: "$prefixPass" }, { $not: "$prefixKey" }] },
33359
+ then: "$name",
33360
+ else: {
33361
+ $cond: {
33362
+ if: { $eq: ["$passType", "pass-key"] },
33363
+ then: { $concat: ["$prefixKey", "$name"] },
33364
+ else: { $concat: ["$prefixPass", "$name"] }
33365
+ }
33366
+ }
33367
+ }
33368
+ }
33369
+ }
33370
+ }
33371
+ ]).toArray().then((results) => results.length ? results[0] : null);
33372
+ }
33373
+ static async checkPassKeyAvailability(visitorPass, passKeys) {
33374
+ if (Array.isArray(visitorPass) && visitorPass.length > 0) {
33375
+ for (let i = 0; i < visitorPass.length; i++) {
33376
+ let pass = await convertObjectIdUtil2(visitorPass[i].keyId, "Pass ID");
33377
+ const getPass = await this.getById2(pass);
33378
+ if (!getPass)
33379
+ throw new Error("Pass not found");
33380
+ if (getPass?.status && getPass?.status.toLowerCase() != "Available".toLowerCase())
33381
+ throw new Error(`Pass ${getPass?.prefixAndName} is ${getPass?.status}`);
33382
+ }
33383
+ }
33384
+ if (Array.isArray(passKeys) && passKeys.length > 0) {
33385
+ for (let i = 0; i < passKeys.length; i++) {
33386
+ let key = await convertObjectIdUtil2(passKeys[i].keyId, "Key ID");
33387
+ const getPass = await this.getById2(key);
33388
+ if (!getPass)
33389
+ throw new Error(`Key not found`);
33390
+ if (getPass?.status && getPass?.status.toLowerCase() != "Available".toLowerCase())
33391
+ throw new Error(`Pass ${getPass?.prefixAndName} is ${getPass?.status}`);
33392
+ }
33393
+ }
33394
+ }
33238
33395
  };
33239
33396
 
33240
33397
  // src/services/visitor-transaction.service.ts
@@ -33271,7 +33428,9 @@ function useVisitorTransactionService() {
33271
33428
  } = useDahuaService();
33272
33429
  const { getAllSites: _getAllSites } = useSiteRepo();
33273
33430
  const { getByUserId: _getByUserId } = usePersonRepo();
33274
- const { add: addVehicle } = useVehicleRepo();
33431
+ const {
33432
+ getBlocklistedVehicleByPlateNumber: _getBlocklistedVehicleByPlateNumber
33433
+ } = useVehicleRepo();
33275
33434
  const { getById: _getUnitById } = useBuildingUnitRepo();
33276
33435
  function extractKeyId(item) {
33277
33436
  if (!item)
@@ -33349,6 +33508,13 @@ function useVisitorTransactionService() {
33349
33508
  const start = value.checkIn ? new Date(value.checkIn) : /* @__PURE__ */ new Date();
33350
33509
  try {
33351
33510
  session?.startTransaction();
33511
+ if (value.plateNumber) {
33512
+ const result2 = await _getBlocklistedVehicleByPlateNumber(
33513
+ value.plateNumber
33514
+ );
33515
+ if (result2)
33516
+ throw new BadRequestError100("Plate number is blocklisted");
33517
+ }
33352
33518
  let camera;
33353
33519
  if (value.site && value.plateNumber) {
33354
33520
  try {
@@ -33414,6 +33580,7 @@ function useVisitorTransactionService() {
33414
33580
  for (let i = 0; i < value.members.length; i += chunkSize) {
33415
33581
  const chunk = value.members.slice(i, i + chunkSize);
33416
33582
  for (const member of chunk) {
33583
+ await KeyRepo.checkPassKeyAvailability(member.visitorPass, member.passKeys);
33417
33584
  if (member.visitorPass && Array.isArray(member.visitorPass) && member.visitorPass.length > 0) {
33418
33585
  for (const vp of member.visitorPass) {
33419
33586
  try {
@@ -33500,6 +33667,7 @@ function useVisitorTransactionService() {
33500
33667
  if (found === 1)
33501
33668
  throw new BadRequestError100("This plate number is blocklisted");
33502
33669
  }
33670
+ await KeyRepo.checkPassKeyAvailability(value.visitorPass, value.passKeys);
33503
33671
  if (value.visitorPass && Array.isArray(value.visitorPass) && value.visitorPass.length > 0 && value.visitorPass) {
33504
33672
  for (const vp of value.visitorPass) {
33505
33673
  try {
@@ -33547,7 +33715,9 @@ function useVisitorTransactionService() {
33547
33715
  password,
33548
33716
  plateNumber: value?.plateNumber
33549
33717
  });
33550
- logger80.info(`Barrier command sent successfully to ${host}`, { response: openBarrier });
33718
+ logger80.info(`Barrier command sent successfully to ${host}`, {
33719
+ response: openBarrier
33720
+ });
33551
33721
  } catch (error) {
33552
33722
  logger80.error(
33553
33723
  `Failed to open barrier at host ${host}. Critical system error:`,
@@ -33687,7 +33857,9 @@ function useVisitorTransactionService() {
33687
33857
  password,
33688
33858
  plateNumber: value?.plateNumber
33689
33859
  });
33690
- logger80.info(`Barrier command sent successfully to ${host}`, { response: openBarrier });
33860
+ logger80.info(`Barrier command sent successfully to ${host}`, {
33861
+ response: openBarrier
33862
+ });
33691
33863
  } catch (error) {
33692
33864
  logger80.error(
33693
33865
  `Failed to open barrier at host ${host}. Critical system error:`,
@@ -33900,7 +34072,12 @@ function useVisitorTransactionController() {
33900
34072
  return;
33901
34073
  } catch (error) {
33902
34074
  logger81.log({ level: "error", message: error.message });
33903
- next(error);
34075
+ console.log("error", error);
34076
+ if (error?.message) {
34077
+ next(new BadRequestError101(error?.message));
34078
+ } else {
34079
+ next(error);
34080
+ }
33904
34081
  return;
33905
34082
  }
33906
34083
  }
@@ -44025,14 +44202,14 @@ function useSiteUnitBillingService() {
44025
44202
  billing_item.units,
44026
44203
  billing_item.site?.toString() || ""
44027
44204
  );
44028
- if (unitsWithOwner?.length) {
44205
+ if (unitsWithOwner?.length > 0) {
44029
44206
  const buildUnitBilling = (unit) => ({
44030
- site: billing_item.site,
44031
- org: billing_item.org,
44207
+ site: billing_item.site.toString(),
44208
+ org: billing_item.org.toString(),
44032
44209
  billItem: billing_item._id,
44033
44210
  billName: billing_item.name,
44034
- unitId: unit._id,
44035
- unit: unit.block + " / " + unit.level + " / " + unit.name,
44211
+ unitId: unit._id.toString(),
44212
+ unit: unit.blockName + " / " + unit.levelName + " / " + unit.name,
44036
44213
  unitOwner: unit.ownerName,
44037
44214
  email: unit.email,
44038
44215
  contactNumber: unit.contact,
@@ -44058,6 +44235,7 @@ function useSiteUnitBillingService() {
44058
44235
  );
44059
44236
  await session.commitTransaction();
44060
44237
  } catch (error) {
44238
+ console.log("BILLING ERROR:", error.message, error);
44061
44239
  logger122.log({
44062
44240
  level: "error",
44063
44241
  message: `Failed to proccess cron billing: ${error.message}`
@@ -56583,6 +56761,7 @@ function useNewDashboardRepo() {
56583
56761
  const area_checklist_namespace_collection = "site.cleaning.schedule.areas";
56584
56762
  const supply_namespace_collection = "site.supplies";
56585
56763
  const work_order_namespace_collection = "work-orders2";
56764
+ const facility_bookings_namespace_collection2 = "facilities-booking";
56586
56765
  const areaChecklistCollection = db.collection(
56587
56766
  area_checklist_namespace_collection
56588
56767
  );
@@ -56598,171 +56777,724 @@ function useNewDashboardRepo() {
56598
56777
  pest_control_services: "Pest Control",
56599
56778
  pool_maintenance_services: "Pool Maintenance"
56600
56779
  };
56601
- async function getMetric(collectionString, siteId, period) {
56602
- const site = toObjectId16(siteId);
56603
- const range = getPeriodRangeWithPrevious(period);
56604
- const collection = db.collection(collectionString);
56605
- const current = await collection.countDocuments({
56606
- site,
56607
- $or: [
56780
+ function formatEndDate(date) {
56781
+ if (typeof date === "string") {
56782
+ const dateWithoutTimezone = date.replace(/\s*\+\d{2}:\d{2}$/, "");
56783
+ date = new Date(dateWithoutTimezone);
56784
+ }
56785
+ const singaporeMoment = moment2.tz(date, "Asia/Singapore");
56786
+ singaporeMoment.set({
56787
+ hour: 23,
56788
+ minute: 59,
56789
+ second: 59,
56790
+ millisecond: 999
56791
+ });
56792
+ return singaporeMoment.toDate();
56793
+ }
56794
+ function getDateRange(p) {
56795
+ const start = /* @__PURE__ */ new Date();
56796
+ start.setHours(0, 0, 0, 0);
56797
+ if (p === "today") {
56798
+ return { $gte: start, $lte: formatEndDate(start) };
56799
+ }
56800
+ const days = p === "thisWeek" ? 7 : 30;
56801
+ const rangeStart = /* @__PURE__ */ new Date();
56802
+ rangeStart.setDate(start.getDate() - days);
56803
+ rangeStart.setHours(0, 0, 0, 0);
56804
+ return { $gte: rangeStart, $lte: formatEndDate(/* @__PURE__ */ new Date()) };
56805
+ }
56806
+ const calculatePercentageChange = (currentCount, previousCount) => {
56807
+ if (previousCount === 0) {
56808
+ return currentCount > 0 ? 100 : 0;
56809
+ }
56810
+ return Math.round((currentCount - previousCount) / previousCount * 100 * 100) / 100;
56811
+ };
56812
+ async function getSecurityDashboard({
56813
+ siteId = "",
56814
+ period = "today" /* TODAY */,
56815
+ type
56816
+ }) {
56817
+ const siteIdObj = toObjectId16(siteId);
56818
+ const visitorMatchObj = {};
56819
+ if (type) {
56820
+ visitorMatchObj.type = type;
56821
+ }
56822
+ const today = /* @__PURE__ */ new Date();
56823
+ today.setHours(0, 0, 0, 0);
56824
+ const yesterday = /* @__PURE__ */ new Date();
56825
+ yesterday.setDate(today.getDate() - 1);
56826
+ yesterday.setHours(0, 0, 0, 0);
56827
+ const yesterdayEnd = new Date(yesterday);
56828
+ yesterdayEnd.setHours(23, 59, 59, 999);
56829
+ const todayEnd = formatEndDate(/* @__PURE__ */ new Date());
56830
+ const periodRange = getDateRange(period);
56831
+ const incidentCollection = db.collection(incidents_namespace_collection);
56832
+ const visitorCollection = db.collection(visitors_namespace_collection);
56833
+ const nfcPatrolLogCollection = db.collection("nfc-patrol-logs");
56834
+ const [
56835
+ workOrderReport,
56836
+ yesterdayWorkOrderReport,
56837
+ todayWorkOrderReport,
56838
+ incidentReport,
56839
+ yesterdayIncidentReport,
56840
+ todayIncidentReport,
56841
+ visitorReport,
56842
+ yesterdayVisitorReport,
56843
+ todayVisitorReport,
56844
+ currentlyOnSiteCount,
56845
+ patrolReport,
56846
+ yesterdayPatrolReport,
56847
+ todayPatrolReport
56848
+ ] = await Promise.all([
56849
+ workOrderCollection.aggregate([
56608
56850
  {
56609
- createdAt: {
56610
- $gte: range.current.start,
56611
- $lte: range.current.end
56851
+ $match: {
56852
+ site: { $in: [siteIdObj, siteId] },
56853
+ service: "Security",
56854
+ createdAt: periodRange,
56855
+ status: { $nin: ["completed"] }
56612
56856
  }
56613
56857
  },
56614
56858
  {
56615
- createdAt: {
56616
- $gte: new Date(range.current.start),
56617
- $lte: new Date(range.current.end)
56859
+ $facet: {
56860
+ total: [{ $count: "count" }],
56861
+ inProgress: [
56862
+ { $match: { status: "in-progress" } },
56863
+ { $count: "count" }
56864
+ ]
56618
56865
  }
56619
56866
  }
56620
- ]
56621
- });
56622
- const previous = await collection.countDocuments({
56623
- site,
56624
- $or: [
56867
+ ]).toArray(),
56868
+ workOrderCollection.aggregate([
56869
+ {
56870
+ $match: {
56871
+ site: { $in: [siteIdObj, siteId] },
56872
+ service: "Security",
56873
+ createdAt: { $gte: yesterday, $lte: yesterdayEnd },
56874
+ status: { $nin: ["completed"] }
56875
+ }
56876
+ },
56877
+ { $count: "count" }
56878
+ ]).toArray(),
56879
+ workOrderCollection.aggregate([
56880
+ {
56881
+ $match: {
56882
+ site: { $in: [siteIdObj, siteId] },
56883
+ service: "Security",
56884
+ createdAt: { $gte: today, $lte: todayEnd },
56885
+ status: { $nin: ["completed"] }
56886
+ }
56887
+ },
56888
+ { $count: "count" }
56889
+ ]).toArray(),
56890
+ incidentCollection.aggregate([
56891
+ {
56892
+ $match: {
56893
+ site: { $in: [siteIdObj, siteId] },
56894
+ status: { $in: ["pending", "Pending"] },
56895
+ createdAt: periodRange
56896
+ }
56897
+ },
56898
+ { $count: "count" }
56899
+ ]).toArray(),
56900
+ incidentCollection.aggregate([
56901
+ {
56902
+ $match: {
56903
+ site: { $in: [siteIdObj, siteId] },
56904
+ status: { $in: ["pending", "Pending"] },
56905
+ createdAt: { $gte: yesterday, $lte: yesterdayEnd }
56906
+ }
56907
+ },
56908
+ { $count: "count" }
56909
+ ]).toArray(),
56910
+ incidentCollection.aggregate([
56911
+ {
56912
+ $match: {
56913
+ site: { $in: [siteIdObj, siteId] },
56914
+ status: { $in: ["pending", "Pending"] },
56915
+ createdAt: { $gte: today, $lte: todayEnd }
56916
+ }
56917
+ },
56918
+ { $count: "count" }
56919
+ ]).toArray(),
56920
+ visitorCollection.aggregate([
56921
+ {
56922
+ $match: {
56923
+ site: { $in: [siteIdObj, siteId] },
56924
+ ...visitorMatchObj,
56925
+ createdAt: periodRange,
56926
+ status: { $ne: "deleted" }
56927
+ }
56928
+ },
56929
+ { $count: "count" }
56930
+ ]).toArray(),
56931
+ visitorCollection.aggregate([
56932
+ {
56933
+ $match: {
56934
+ site: { $in: [siteIdObj, siteId] },
56935
+ ...visitorMatchObj,
56936
+ createdAt: { $gte: yesterday, $lte: yesterdayEnd },
56937
+ status: { $ne: "deleted" }
56938
+ }
56939
+ },
56940
+ { $count: "count" }
56941
+ ]).toArray(),
56942
+ visitorCollection.aggregate([
56625
56943
  {
56626
- createdAt: {
56627
- $gte: range.previous.start,
56628
- $lte: range.previous.end
56944
+ $match: {
56945
+ site: { $in: [siteIdObj, siteId] },
56946
+ ...visitorMatchObj,
56947
+ createdAt: { $gte: today, $lte: todayEnd },
56948
+ status: { $ne: "deleted" }
56629
56949
  }
56630
56950
  },
56951
+ { $count: "count" }
56952
+ ]).toArray(),
56953
+ visitorCollection.countDocuments({
56954
+ site: { $in: [siteIdObj, siteId] },
56955
+ ...visitorMatchObj,
56956
+ checkIn: { $ne: null },
56957
+ checkOut: null,
56958
+ status: { $ne: "deleted" }
56959
+ }),
56960
+ nfcPatrolLogCollection.aggregate([
56631
56961
  {
56632
- createdAt: {
56633
- $gte: new Date(range.previous.start),
56634
- $lte: new Date(range.previous.end)
56962
+ $match: {
56963
+ site: { $in: [siteIdObj, siteId] },
56964
+ createdAt: periodRange
56965
+ }
56966
+ },
56967
+ {
56968
+ $unwind: "$checkPoints"
56969
+ },
56970
+ {
56971
+ $facet: {
56972
+ total: [{ $count: "count" }],
56973
+ completed: [
56974
+ { $match: { "checkPoints.status": "Completed" } },
56975
+ { $count: "count" }
56976
+ ],
56977
+ skipped: [
56978
+ { $match: { "checkPoints.status": "Skipped" } },
56979
+ { $count: "count" }
56980
+ ]
56635
56981
  }
56636
56982
  }
56637
- ]
56638
- });
56639
- return {
56640
- count: current,
56641
- percentage: calculatePercentage(current, previous)
56983
+ ]).toArray(),
56984
+ nfcPatrolLogCollection.aggregate([
56985
+ {
56986
+ $match: {
56987
+ site: { $in: [siteIdObj, siteId] },
56988
+ createdAt: { $gte: yesterday, $lte: yesterdayEnd }
56989
+ }
56990
+ },
56991
+ {
56992
+ $unwind: "$checkPoints"
56993
+ },
56994
+ {
56995
+ $facet: {
56996
+ total: [{ $count: "count" }],
56997
+ completed: [
56998
+ { $match: { "checkPoints.status": "Completed" } },
56999
+ { $count: "count" }
57000
+ ],
57001
+ skipped: [
57002
+ { $match: { "checkPoints.status": "Skipped" } },
57003
+ { $count: "count" }
57004
+ ]
57005
+ }
57006
+ }
57007
+ ]).toArray(),
57008
+ nfcPatrolLogCollection.aggregate([
57009
+ {
57010
+ $match: {
57011
+ site: { $in: [siteIdObj, siteId] },
57012
+ createdAt: { $gte: today, $lte: todayEnd }
57013
+ }
57014
+ },
57015
+ {
57016
+ $unwind: "$checkPoints"
57017
+ },
57018
+ {
57019
+ $facet: {
57020
+ total: [{ $count: "count" }],
57021
+ completed: [
57022
+ { $match: { "checkPoints.status": "Completed" } },
57023
+ { $count: "count" }
57024
+ ],
57025
+ skipped: [
57026
+ { $match: { "checkPoints.status": "Skipped" } },
57027
+ { $count: "count" }
57028
+ ]
57029
+ }
57030
+ }
57031
+ ]).toArray()
57032
+ ]);
57033
+ const wFacet = workOrderReport[0] ?? { total: [], inProgress: [] };
57034
+ const pFacet = patrolReport[0] ?? {
57035
+ total: [],
57036
+ completed: [],
57037
+ skipped: []
56642
57038
  };
56643
- }
56644
- async function getSecurityDashboard({
56645
- siteId = "",
56646
- feedback = "today" /* TODAY */,
56647
- workOrder = "today" /* TODAY */,
56648
- vehicle = "today" /* TODAY */,
56649
- building = "today" /* TODAY */,
56650
- visitor = "today" /* TODAY */,
56651
- incident = "today" /* TODAY */,
56652
- guest = "today" /* TODAY */
56653
- }) {
56654
- const feedbacks = await getMetric(
56655
- feedbacks_namespace_collection,
56656
- siteId,
56657
- feedback
56658
- );
56659
- const workOrders = await getMetric(
56660
- work_orders_namespace_collection,
56661
- siteId,
56662
- workOrder
56663
- );
56664
- const vehicles = await getMetric(
56665
- vehicles_namespace_collection,
56666
- siteId,
56667
- vehicle
56668
- );
56669
- const buildings = await getMetric(
56670
- buildings_namespace_collection,
56671
- siteId,
56672
- building
56673
- );
56674
- const visitors = await getMetric(
56675
- visitors_namespace_collection,
56676
- siteId,
56677
- visitor
56678
- );
56679
- const incidents = await getMetric(
56680
- incidents_namespace_collection,
56681
- siteId,
56682
- incident
57039
+ const totalCheckpoints = pFacet.total[0]?.count ?? 0;
57040
+ const completedCheckpoints = pFacet.completed[0]?.count ?? 0;
57041
+ const skippedCheckpoints = pFacet.skipped[0]?.count ?? 0;
57042
+ const complianceRate = totalCheckpoints > 0 ? Math.round(completedCheckpoints / totalCheckpoints * 100 * 100) / 100 : 100;
57043
+ const yPatrolFacet = yesterdayPatrolReport[0] ?? {
57044
+ total: [],
57045
+ completed: []
57046
+ };
57047
+ const yTotal = yPatrolFacet.total[0]?.count ?? 0;
57048
+ const yCompleted = yPatrolFacet.completed[0]?.count ?? 0;
57049
+ const yesterdayCompliance = yTotal > 0 ? yCompleted / yTotal * 100 : 0;
57050
+ const tPatrolFacet = todayPatrolReport[0] ?? {
57051
+ total: [],
57052
+ completed: []
57053
+ };
57054
+ const tTotal = tPatrolFacet.total[0]?.count ?? 0;
57055
+ const tCompleted = tPatrolFacet.completed[0]?.count ?? 0;
57056
+ const todayCompliance = tTotal > 0 ? tCompleted / tTotal * 100 : 0;
57057
+ const todayString = moment2.tz("Asia/Singapore").format("YYYY-MM-DD");
57058
+ const dayIndex = moment2.tz("Asia/Singapore").day();
57059
+ const routes = await db.collection("nfc-patrol-routes").find({
57060
+ site: { $in: [siteIdObj, siteId] },
57061
+ days: { $in: [dayIndex] },
57062
+ status: { $ne: "Inactive" }
57063
+ }).toArray();
57064
+ const expandedRoutes = [];
57065
+ for (const route of routes) {
57066
+ if (route.startTimes && Array.isArray(route.startTimes)) {
57067
+ for (const startTime of route.startTimes) {
57068
+ expandedRoutes.push({
57069
+ route,
57070
+ startTime,
57071
+ itemIndex: 0
57072
+ });
57073
+ }
57074
+ }
57075
+ }
57076
+ expandedRoutes.sort((a, b) => a.startTime.localeCompare(b.startTime));
57077
+ const limitedRoutes = expandedRoutes.slice(0, 4);
57078
+ limitedRoutes.forEach((item, idx) => {
57079
+ item.itemIndex = idx + 1;
57080
+ });
57081
+ const activePatrolItems = await Promise.all(
57082
+ limitedRoutes.map(async ({ route, startTime, itemIndex }) => {
57083
+ const log = await db.collection("nfc-patrol-logs").findOne({
57084
+ site: { $in: [siteIdObj, siteId] },
57085
+ date: todayString,
57086
+ "route._id": { $in: [route._id, route._id.toString()] },
57087
+ "route.startTime": startTime
57088
+ });
57089
+ let person = "Unassigned";
57090
+ if (log && log.createdBy) {
57091
+ const userDoc = await db.collection("users").findOne({
57092
+ _id: toObjectId16(log.createdBy)
57093
+ });
57094
+ if (userDoc && userDoc.name) {
57095
+ person = userDoc.name;
57096
+ }
57097
+ }
57098
+ let status = "pending";
57099
+ if (log) {
57100
+ status = "completed";
57101
+ } else {
57102
+ const routeTime = moment2.tz(
57103
+ `${todayString} ${startTime}`,
57104
+ "YYYY-MM-DD HH:mm",
57105
+ "Asia/Singapore"
57106
+ );
57107
+ const nowSg = moment2.tz("Asia/Singapore");
57108
+ const diffMinutes = nowSg.diff(routeTime, "minutes");
57109
+ if (diffMinutes >= 0) {
57110
+ if (diffMinutes <= 120) {
57111
+ status = "on paused";
57112
+ } else {
57113
+ status = "incomplete";
57114
+ }
57115
+ } else {
57116
+ status = "pending";
57117
+ }
57118
+ }
57119
+ return {
57120
+ id: `${route._id.toString()}_${startTime}`,
57121
+ title: route.name,
57122
+ subtitle: `ID${String(itemIndex).padStart(3, "0")}`,
57123
+ person,
57124
+ status,
57125
+ time: startTime
57126
+ };
57127
+ })
56683
57128
  );
56684
- const guests = await getMetric(guests_namespace_collection, siteId, guest);
56685
57129
  const data = {
56686
- feedbacks,
56687
- workOrders,
56688
- vehicles,
56689
- buildings,
56690
- visitors,
56691
- incidents,
56692
- guests
57130
+ openWorkOrder: {
57131
+ count: wFacet.total[0]?.count ?? 0,
57132
+ inProgress: wFacet.inProgress[0]?.count ?? 0,
57133
+ percentage: calculatePercentageChange(
57134
+ todayWorkOrderReport[0]?.count ?? 0,
57135
+ yesterdayWorkOrderReport[0]?.count ?? 0
57136
+ )
57137
+ },
57138
+ openIncidents: {
57139
+ count: incidentReport[0]?.count ?? 0,
57140
+ highSeverity: 0,
57141
+ percentage: calculatePercentageChange(
57142
+ todayIncidentReport[0]?.count ?? 0,
57143
+ yesterdayIncidentReport[0]?.count ?? 0
57144
+ )
57145
+ },
57146
+ visitors: {
57147
+ count: visitorReport[0]?.count ?? 0,
57148
+ currentlyOnSite: currentlyOnSiteCount,
57149
+ percentage: calculatePercentageChange(
57150
+ todayVisitorReport[0]?.count ?? 0,
57151
+ yesterdayVisitorReport[0]?.count ?? 0
57152
+ )
57153
+ },
57154
+ patrolCompliance: {
57155
+ count: complianceRate,
57156
+ missedCheckpoints: skippedCheckpoints,
57157
+ missed: skippedCheckpoints,
57158
+ percentage: calculatePercentageChange(
57159
+ todayCompliance,
57160
+ yesterdayCompliance
57161
+ )
57162
+ },
57163
+ activePatrolItems
56693
57164
  };
56694
57165
  return data;
56695
57166
  }
56696
- async function getPropertyManagementDashboard({
56697
- siteId = "",
56698
- feedback = "today" /* TODAY */,
56699
- workOrder = "today" /* TODAY */,
56700
- sitePeople = "today" /* TODAY */,
56701
- facilityBooking = "today" /* TODAY */,
56702
- bulletinBoard = "today" /* TODAY */,
56703
- event = "today" /* TODAY */,
56704
- vehicle = "today" /* TODAY */,
56705
- building = "today" /* TODAY */,
56706
- visitor = "today" /* TODAY */,
56707
- incident = "today" /* TODAY */
56708
- }) {
56709
- const feedbacks = await getMetric(
56710
- feedbacks_namespace_collection,
56711
- siteId,
56712
- feedback
56713
- );
56714
- const workOrders = await getMetric(
56715
- work_orders_namespace_collection,
56716
- siteId,
56717
- workOrder
56718
- );
56719
- const vehicles = await getMetric(
56720
- vehicles_namespace_collection,
56721
- siteId,
56722
- vehicle
56723
- );
56724
- const buildings = await getMetric(
56725
- buildings_namespace_collection,
56726
- siteId,
56727
- building
56728
- );
56729
- const visitors = await getMetric(
56730
- visitors_namespace_collection,
56731
- siteId,
56732
- visitor
56733
- );
56734
- const incidents = await getMetric(
56735
- incidents_namespace_collection,
56736
- siteId,
56737
- incident
56738
- );
56739
- const _sitePeople = await getMetric(
56740
- site_people_namespace_collection,
56741
- siteId,
56742
- sitePeople
57167
+ async function getPropertyManagementDashboard(siteId, period = "today" /* TODAY */, type, facility) {
57168
+ const siteIdObj = toObjectId16(siteId);
57169
+ const startOfToday = moment2.tz("Asia/Singapore").startOf("day").toDate();
57170
+ const endOfToday = moment2.tz("Asia/Singapore").endOf("day").toDate();
57171
+ const upcomingEvents = await db.collection(events_namespace_collection).find({
57172
+ site: { $in: [siteIdObj, siteId] },
57173
+ status: { $nin: ["deleted", "Deleted"] },
57174
+ $or: [
57175
+ { dateTime: { $gte: startOfToday } },
57176
+ { dateTime: { $gte: startOfToday.toISOString() } }
57177
+ ]
57178
+ }).sort({ dateTime: 1 }).limit(4).toArray();
57179
+ const todayReminders = await db.collection(events_namespace_collection).find({
57180
+ site: { $in: [siteIdObj, siteId] },
57181
+ status: { $nin: ["deleted", "Deleted"] },
57182
+ $or: [
57183
+ { dateTime: { $gte: startOfToday, $lte: endOfToday } },
57184
+ {
57185
+ dateTime: {
57186
+ $gte: startOfToday.toISOString(),
57187
+ $lte: endOfToday.toISOString()
57188
+ }
57189
+ }
57190
+ ]
57191
+ }).sort({ dateTime: 1 }).limit(4).toArray();
57192
+ const [pendingIncidentDocs, pendingFacilityBookingDocs] = await Promise.all(
57193
+ [
57194
+ db.collection(incidents_namespace_collection).find({
57195
+ site: { $in: [siteIdObj, siteId] },
57196
+ status: { $in: ["pending", "Pending"] }
57197
+ }).sort({ createdAt: -1 }).toArray(),
57198
+ db.collection(facility_bookings_namespace_collection2).find({
57199
+ site: { $in: [siteIdObj, siteId] },
57200
+ status: { $in: ["Pending", "pending", "For Review", "for review"] }
57201
+ }).sort({ createdAt: -1 }).toArray()
57202
+ ]
56743
57203
  );
56744
- const bulletinBoards = await getMetric(
56745
- bulletin_boards_namespace_collection,
56746
- siteId,
56747
- bulletinBoard
57204
+ const pendingIncidentCount = pendingIncidentDocs.length;
57205
+ const pendingFacilityBookingCount = pendingFacilityBookingDocs.length;
57206
+ const todayAttentions = [];
57207
+ if (pendingIncidentCount > 0) {
57208
+ todayAttentions.push({
57209
+ id: "incidents-pending",
57210
+ title: `${pendingIncidentCount} incident${pendingIncidentCount === 1 ? "" : "s"} pending acknowledge`,
57211
+ createdAt: pendingIncidentDocs[0].updatedAt || pendingIncidentDocs[0].createdAt || /* @__PURE__ */ new Date()
57212
+ });
57213
+ }
57214
+ if (pendingFacilityBookingCount > 0) {
57215
+ todayAttentions.push({
57216
+ id: "facility-booking-pending",
57217
+ title: `${pendingFacilityBookingCount} facility booking${pendingFacilityBookingCount === 1 ? "" : "s"} need approval`,
57218
+ createdAt: pendingFacilityBookingDocs[0].createdAt || /* @__PURE__ */ new Date()
57219
+ });
57220
+ }
57221
+ todayAttentions.sort(
57222
+ (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
56748
57223
  );
56749
- const events = await getMetric(events_namespace_collection, siteId, event);
56750
- const facilityBookings = await getMetric(
56751
- facility_bookings_namespace_collection,
56752
- siteId,
56753
- facilityBooking
57224
+ const visitorMatchObj = {};
57225
+ if (type) {
57226
+ visitorMatchObj.type = type;
57227
+ }
57228
+ const facilityMatchObj = {};
57229
+ if (facility) {
57230
+ try {
57231
+ facilityMatchObj.facility = { $in: [facility, new ObjectId121(facility)] };
57232
+ } catch (e) {
57233
+ facilityMatchObj.facility = facility;
57234
+ }
57235
+ }
57236
+ const today = /* @__PURE__ */ new Date();
57237
+ today.setHours(0, 0, 0, 0);
57238
+ const yesterday = /* @__PURE__ */ new Date();
57239
+ yesterday.setDate(today.getDate() - 1);
57240
+ yesterday.setHours(0, 0, 0, 0);
57241
+ const yesterdayEnd = new Date(yesterday);
57242
+ yesterdayEnd.setHours(23, 59, 59, 999);
57243
+ const todayEnd = formatEndDate(/* @__PURE__ */ new Date());
57244
+ const periodRange = getDateRange(period);
57245
+ const incidentCollection = db.collection(incidents_namespace_collection);
57246
+ const visitorCollection = db.collection(visitors_namespace_collection);
57247
+ const facilityCollection = db.collection(
57248
+ facility_bookings_namespace_collection2
56754
57249
  );
57250
+ const [
57251
+ workOrderReport,
57252
+ yesterdayWorkOrderReport,
57253
+ todayWorkOrderReport,
57254
+ incidentReport,
57255
+ yesterdayIncidentReport,
57256
+ todayIncidentReport,
57257
+ visitorReport,
57258
+ yesterdayVisitorReport,
57259
+ todayVisitorReport,
57260
+ currentlyOnSiteCount,
57261
+ facilityReport,
57262
+ yesterdayFacilityReport,
57263
+ todayFacilityReport
57264
+ ] = await Promise.all([
57265
+ workOrderCollection.aggregate([
57266
+ {
57267
+ $match: {
57268
+ site: { $in: [siteIdObj, siteId] },
57269
+ createdAt: periodRange,
57270
+ status: { $nin: ["completed"] }
57271
+ }
57272
+ },
57273
+ {
57274
+ $facet: {
57275
+ total: [{ $count: "count" }],
57276
+ inProgress: [
57277
+ { $match: { status: "in-progress" } },
57278
+ { $count: "count" }
57279
+ ]
57280
+ }
57281
+ }
57282
+ ]).toArray(),
57283
+ workOrderCollection.aggregate([
57284
+ {
57285
+ $match: {
57286
+ site: { $in: [siteIdObj, siteId] },
57287
+ createdAt: { $gte: yesterday, $lte: yesterdayEnd },
57288
+ status: { $nin: ["completed"] }
57289
+ }
57290
+ },
57291
+ { $count: "count" }
57292
+ ]).toArray(),
57293
+ workOrderCollection.aggregate([
57294
+ {
57295
+ $match: {
57296
+ site: { $in: [siteIdObj, siteId] },
57297
+ createdAt: { $gte: today, $lte: todayEnd },
57298
+ status: { $nin: ["completed"] }
57299
+ }
57300
+ },
57301
+ { $count: "count" }
57302
+ ]).toArray(),
57303
+ incidentCollection.aggregate([
57304
+ {
57305
+ $match: {
57306
+ site: { $in: [siteIdObj, siteId] },
57307
+ status: { $in: ["pending", "Pending"] },
57308
+ createdAt: periodRange
57309
+ }
57310
+ },
57311
+ { $count: "count" }
57312
+ ]).toArray(),
57313
+ incidentCollection.aggregate([
57314
+ {
57315
+ $match: {
57316
+ site: { $in: [siteIdObj, siteId] },
57317
+ status: { $in: ["pending", "Pending"] },
57318
+ createdAt: { $gte: yesterday, $lte: yesterdayEnd }
57319
+ }
57320
+ },
57321
+ { $count: "count" }
57322
+ ]).toArray(),
57323
+ incidentCollection.aggregate([
57324
+ {
57325
+ $match: {
57326
+ site: { $in: [siteIdObj, siteId] },
57327
+ status: { $in: ["pending", "Pending"] },
57328
+ createdAt: { $gte: today, $lte: todayEnd }
57329
+ }
57330
+ },
57331
+ { $count: "count" }
57332
+ ]).toArray(),
57333
+ visitorCollection.aggregate([
57334
+ {
57335
+ $match: {
57336
+ site: { $in: [siteIdObj, siteId] },
57337
+ ...visitorMatchObj,
57338
+ createdAt: periodRange,
57339
+ status: { $ne: "deleted" }
57340
+ }
57341
+ },
57342
+ { $count: "count" }
57343
+ ]).toArray(),
57344
+ visitorCollection.aggregate([
57345
+ {
57346
+ $match: {
57347
+ site: { $in: [siteIdObj, siteId] },
57348
+ ...visitorMatchObj,
57349
+ createdAt: { $gte: yesterday, $lte: yesterdayEnd },
57350
+ status: { $ne: "deleted" }
57351
+ }
57352
+ },
57353
+ { $count: "count" }
57354
+ ]).toArray(),
57355
+ visitorCollection.aggregate([
57356
+ {
57357
+ $match: {
57358
+ site: { $in: [siteIdObj, siteId] },
57359
+ ...visitorMatchObj,
57360
+ createdAt: { $gte: today, $lte: todayEnd },
57361
+ status: { $ne: "deleted" }
57362
+ }
57363
+ },
57364
+ { $count: "count" }
57365
+ ]).toArray(),
57366
+ visitorCollection.countDocuments({
57367
+ site: { $in: [siteIdObj, siteId] },
57368
+ ...visitorMatchObj,
57369
+ checkIn: { $ne: null },
57370
+ checkOut: null,
57371
+ status: { $ne: "deleted" }
57372
+ }),
57373
+ facilityCollection.aggregate([
57374
+ {
57375
+ $match: {
57376
+ site: { $in: [siteIdObj, siteId] },
57377
+ ...facilityMatchObj,
57378
+ $or: [
57379
+ { createdAt: periodRange },
57380
+ {
57381
+ createdAt: {
57382
+ $gte: periodRange.$gte.toISOString(),
57383
+ $lte: periodRange.$lte.toISOString()
57384
+ }
57385
+ }
57386
+ ],
57387
+ status: { $nin: ["deleted", "Deleted"] }
57388
+ }
57389
+ },
57390
+ {
57391
+ $facet: {
57392
+ total: [{ $count: "count" }],
57393
+ ongoing: [
57394
+ {
57395
+ $match: {
57396
+ status: {
57397
+ $in: ["Approved", "Ongoing"]
57398
+ }
57399
+ }
57400
+ },
57401
+ { $count: "count" }
57402
+ ],
57403
+ waitingApproval: [
57404
+ {
57405
+ $match: {
57406
+ status: {
57407
+ $in: ["Pending", "pending", "For Review", "for review"]
57408
+ }
57409
+ }
57410
+ },
57411
+ { $count: "count" }
57412
+ ]
57413
+ }
57414
+ }
57415
+ ]).toArray(),
57416
+ facilityCollection.aggregate([
57417
+ {
57418
+ $match: {
57419
+ site: { $in: [siteIdObj, siteId] },
57420
+ ...facilityMatchObj,
57421
+ $or: [
57422
+ { createdAt: { $gte: yesterday, $lte: yesterdayEnd } },
57423
+ {
57424
+ createdAt: {
57425
+ $gte: yesterday.toISOString(),
57426
+ $lte: yesterdayEnd.toISOString()
57427
+ }
57428
+ }
57429
+ ],
57430
+ status: { $nin: ["deleted", "Deleted"] }
57431
+ }
57432
+ },
57433
+ { $count: "count" }
57434
+ ]).toArray(),
57435
+ facilityCollection.aggregate([
57436
+ {
57437
+ $match: {
57438
+ site: { $in: [siteIdObj, siteId] },
57439
+ ...facilityMatchObj,
57440
+ $or: [
57441
+ { createdAt: { $gte: today, $lte: todayEnd } },
57442
+ {
57443
+ createdAt: {
57444
+ $gte: today.toISOString(),
57445
+ $lte: todayEnd.toISOString()
57446
+ }
57447
+ }
57448
+ ],
57449
+ status: { $nin: ["deleted", "Deleted"] }
57450
+ }
57451
+ },
57452
+ { $count: "count" }
57453
+ ]).toArray()
57454
+ ]);
57455
+ const wFacet = workOrderReport[0] ?? { total: [], inProgress: [] };
57456
+ const fFacet = facilityReport[0] ?? {
57457
+ total: [],
57458
+ ongoing: [],
57459
+ waitingApproval: []
57460
+ };
56755
57461
  const data = {
56756
- feedbacks,
56757
- workOrders,
56758
- vehicles,
56759
- buildings,
56760
- visitors,
56761
- incidents,
56762
- sitePeople: _sitePeople,
56763
- bulletinBoards,
56764
- events,
56765
- facilityBookings
57462
+ openWorkOrder: {
57463
+ count: wFacet.total[0]?.count ?? 0,
57464
+ inProgress: wFacet.inProgress[0]?.count ?? 0,
57465
+ percentage: calculatePercentageChange(
57466
+ todayWorkOrderReport[0]?.count ?? 0,
57467
+ yesterdayWorkOrderReport[0]?.count ?? 0
57468
+ )
57469
+ },
57470
+ openIncidents: {
57471
+ count: incidentReport[0]?.count ?? 0,
57472
+ highSeverity: 0,
57473
+ percentage: calculatePercentageChange(
57474
+ todayIncidentReport[0]?.count ?? 0,
57475
+ yesterdayIncidentReport[0]?.count ?? 0
57476
+ )
57477
+ },
57478
+ visitors: {
57479
+ count: visitorReport[0]?.count ?? 0,
57480
+ currentlyOnSite: currentlyOnSiteCount,
57481
+ percentage: calculatePercentageChange(
57482
+ todayVisitorReport[0]?.count ?? 0,
57483
+ yesterdayVisitorReport[0]?.count ?? 0
57484
+ )
57485
+ },
57486
+ facilityBooking: {
57487
+ count: fFacet.total[0]?.count ?? 0,
57488
+ ongoing: fFacet.ongoing[0]?.count ?? 0,
57489
+ waitingApproval: fFacet.waitingApproval[0]?.count ?? 0,
57490
+ percentage: calculatePercentageChange(
57491
+ todayFacilityReport[0]?.count ?? 0,
57492
+ yesterdayFacilityReport[0]?.count ?? 0
57493
+ )
57494
+ },
57495
+ upcomingEvents,
57496
+ todayReminders,
57497
+ todayAttentions
56766
57498
  };
56767
57499
  return data;
56768
57500
  }
@@ -56792,61 +57524,13 @@ function useNewDashboardRepo() {
56792
57524
  async function getServiceDashboard({
56793
57525
  site,
56794
57526
  serviceType,
56795
- period = "today" /* TODAY */,
56796
- type,
56797
- facility
57527
+ period = "today" /* TODAY */
56798
57528
  }) {
56799
57529
  try {
56800
57530
  site = new ObjectId121(site);
56801
57531
  } catch (error) {
56802
57532
  throw new BadRequestError182("Invalid site ID format.");
56803
57533
  }
56804
- const visitorMatchObj = {};
56805
- if (type) {
56806
- visitorMatchObj.type = type;
56807
- }
56808
- const facilityMatchObj = {};
56809
- if (facility) {
56810
- try {
56811
- facilityMatchObj.facility = { $in: [facility, new ObjectId121(facility)] };
56812
- } catch (e) {
56813
- facilityMatchObj.facility = facility;
56814
- }
56815
- }
56816
- function formatEndDate(date) {
56817
- if (typeof date === "string") {
56818
- const dateWithoutTimezone = date.replace(/\s*\+\d{2}:\d{2}$/, "");
56819
- date = new Date(dateWithoutTimezone);
56820
- }
56821
- const singaporeMoment = moment2.tz(date, "Asia/Singapore");
56822
- singaporeMoment.set({
56823
- hour: 23,
56824
- minute: 59,
56825
- second: 59,
56826
- millisecond: 999
56827
- });
56828
- return singaporeMoment.toDate();
56829
- }
56830
- function getDateRange(p) {
56831
- const start = /* @__PURE__ */ new Date();
56832
- start.setHours(0, 0, 0, 0);
56833
- if (p === "today") {
56834
- return { $gte: start, $lte: formatEndDate(start) };
56835
- }
56836
- const days = p === "thisWeek" ? 7 : 30;
56837
- const rangeStart = /* @__PURE__ */ new Date();
56838
- rangeStart.setDate(start.getDate() - days);
56839
- rangeStart.setHours(0, 0, 0, 0);
56840
- return { $gte: rangeStart, $lte: formatEndDate(/* @__PURE__ */ new Date()) };
56841
- }
56842
- const calculatePercentageChange = (currentCount, previousCount) => {
56843
- if (previousCount === 0) {
56844
- return currentCount > 0 ? 100 : 0;
56845
- }
56846
- return Math.round(
56847
- (currentCount - previousCount) / previousCount * 100 * 100
56848
- ) / 100;
56849
- };
56850
57534
  const today = /* @__PURE__ */ new Date();
56851
57535
  today.setHours(0, 0, 0, 0);
56852
57536
  const yesterday = /* @__PURE__ */ new Date();
@@ -56857,530 +57541,6 @@ function useNewDashboardRepo() {
56857
57541
  const todayEnd = formatEndDate(/* @__PURE__ */ new Date());
56858
57542
  const periodRange = getDateRange(period);
56859
57543
  try {
56860
- if (serviceType === "property_management_agency" /* PROPERTY_MANAGEMENT_AGENCY */) {
56861
- const incidentCollection = db.collection(
56862
- incidents_namespace_collection
56863
- );
56864
- const visitorCollection = db.collection(visitors_namespace_collection);
56865
- const facilityCollection = db.collection(
56866
- facility_bookings_namespace_collection
56867
- );
56868
- const [
56869
- workOrderReport2,
56870
- yesterdayWorkOrderReport2,
56871
- todayWorkOrderReport2,
56872
- incidentReport,
56873
- yesterdayIncidentReport,
56874
- todayIncidentReport,
56875
- visitorReport,
56876
- yesterdayVisitorReport,
56877
- todayVisitorReport,
56878
- currentlyOnSiteCount,
56879
- facilityReport,
56880
- yesterdayFacilityReport,
56881
- todayFacilityReport
56882
- ] = await Promise.all([
56883
- workOrderCollection.aggregate([
56884
- {
56885
- $match: {
56886
- site,
56887
- createdAt: periodRange,
56888
- status: { $nin: ["completed"] }
56889
- }
56890
- },
56891
- {
56892
- $facet: {
56893
- total: [{ $count: "count" }],
56894
- inProgress: [
56895
- { $match: { status: "in-progress" } },
56896
- { $count: "count" }
56897
- ]
56898
- }
56899
- }
56900
- ]).toArray(),
56901
- workOrderCollection.aggregate([
56902
- {
56903
- $match: {
56904
- site,
56905
- createdAt: { $gte: yesterday, $lte: yesterdayEnd },
56906
- status: { $nin: ["completed"] }
56907
- }
56908
- },
56909
- { $count: "count" }
56910
- ]).toArray(),
56911
- workOrderCollection.aggregate([
56912
- {
56913
- $match: {
56914
- site,
56915
- createdAt: { $gte: today, $lte: todayEnd },
56916
- status: { $nin: ["completed"] }
56917
- }
56918
- },
56919
- { $count: "count" }
56920
- ]).toArray(),
56921
- incidentCollection.aggregate([
56922
- {
56923
- $match: {
56924
- site,
56925
- status: "pending",
56926
- createdAt: periodRange
56927
- }
56928
- },
56929
- { $count: "count" }
56930
- ]).toArray(),
56931
- incidentCollection.aggregate([
56932
- {
56933
- $match: {
56934
- site,
56935
- status: "pending",
56936
- createdAt: { $gte: yesterday, $lte: yesterdayEnd }
56937
- }
56938
- },
56939
- { $count: "count" }
56940
- ]).toArray(),
56941
- incidentCollection.aggregate([
56942
- {
56943
- $match: {
56944
- site,
56945
- status: "pending",
56946
- createdAt: { $gte: today, $lte: todayEnd }
56947
- }
56948
- },
56949
- { $count: "count" }
56950
- ]).toArray(),
56951
- visitorCollection.aggregate([
56952
- {
56953
- $match: {
56954
- site,
56955
- ...visitorMatchObj,
56956
- createdAt: periodRange,
56957
- status: { $ne: "deleted" }
56958
- }
56959
- },
56960
- { $count: "count" }
56961
- ]).toArray(),
56962
- visitorCollection.aggregate([
56963
- {
56964
- $match: {
56965
- site,
56966
- ...visitorMatchObj,
56967
- createdAt: { $gte: yesterday, $lte: yesterdayEnd },
56968
- status: { $ne: "deleted" }
56969
- }
56970
- },
56971
- { $count: "count" }
56972
- ]).toArray(),
56973
- visitorCollection.aggregate([
56974
- {
56975
- $match: {
56976
- site,
56977
- ...visitorMatchObj,
56978
- createdAt: { $gte: today, $lte: todayEnd },
56979
- status: { $ne: "deleted" }
56980
- }
56981
- },
56982
- { $count: "count" }
56983
- ]).toArray(),
56984
- visitorCollection.countDocuments({
56985
- site,
56986
- ...visitorMatchObj,
56987
- checkIn: { $ne: null },
56988
- checkOut: null,
56989
- status: { $ne: "deleted" }
56990
- }),
56991
- facilityCollection.aggregate([
56992
- {
56993
- $match: {
56994
- site,
56995
- ...facilityMatchObj,
56996
- $or: [
56997
- { createdAt: periodRange },
56998
- {
56999
- createdAt: {
57000
- $gte: periodRange.$gte.toISOString(),
57001
- $lte: periodRange.$lte.toISOString()
57002
- }
57003
- }
57004
- ],
57005
- status: { $nin: ["deleted", "Deleted"] }
57006
- }
57007
- },
57008
- {
57009
- $facet: {
57010
- total: [{ $count: "count" }],
57011
- ongoing: [
57012
- {
57013
- $match: {
57014
- status: {
57015
- $in: ["Approved", "Ongoing"]
57016
- }
57017
- }
57018
- },
57019
- { $count: "count" }
57020
- ],
57021
- waitingApproval: [
57022
- {
57023
- $match: {
57024
- status: {
57025
- $in: ["Pending", "For Review"]
57026
- }
57027
- }
57028
- },
57029
- { $count: "count" }
57030
- ]
57031
- }
57032
- }
57033
- ]).toArray(),
57034
- facilityCollection.aggregate([
57035
- {
57036
- $match: {
57037
- site,
57038
- ...facilityMatchObj,
57039
- $or: [
57040
- { createdAt: { $gte: yesterday, $lte: yesterdayEnd } },
57041
- {
57042
- createdAt: {
57043
- $gte: yesterday.toISOString(),
57044
- $lte: yesterdayEnd.toISOString()
57045
- }
57046
- }
57047
- ],
57048
- status: { $nin: ["deleted", "Deleted"] }
57049
- }
57050
- },
57051
- { $count: "count" }
57052
- ]).toArray(),
57053
- facilityCollection.aggregate([
57054
- {
57055
- $match: {
57056
- site,
57057
- ...facilityMatchObj,
57058
- $or: [
57059
- { createdAt: { $gte: today, $lte: todayEnd } },
57060
- {
57061
- createdAt: {
57062
- $gte: today.toISOString(),
57063
- $lte: todayEnd.toISOString()
57064
- }
57065
- }
57066
- ],
57067
- status: { $nin: ["deleted", "Deleted"] }
57068
- }
57069
- },
57070
- { $count: "count" }
57071
- ]).toArray()
57072
- ]);
57073
- const wFacet2 = workOrderReport2[0] ?? { total: [], inProgress: [] };
57074
- const fFacet = facilityReport[0] ?? {
57075
- total: [],
57076
- ongoing: [],
57077
- waitingApproval: []
57078
- };
57079
- const result2 = {
57080
- openWorkOrder: {
57081
- count: wFacet2.total[0]?.count ?? 0,
57082
- inProgress: wFacet2.inProgress[0]?.count ?? 0,
57083
- percentage: calculatePercentageChange(
57084
- todayWorkOrderReport2[0]?.count ?? 0,
57085
- yesterdayWorkOrderReport2[0]?.count ?? 0
57086
- )
57087
- },
57088
- openIncidents: {
57089
- count: incidentReport[0]?.count ?? 0,
57090
- highSeverity: 0,
57091
- percentage: calculatePercentageChange(
57092
- todayIncidentReport[0]?.count ?? 0,
57093
- yesterdayIncidentReport[0]?.count ?? 0
57094
- )
57095
- },
57096
- visitors: {
57097
- count: visitorReport[0]?.count ?? 0,
57098
- currentlyOnSite: currentlyOnSiteCount,
57099
- percentage: calculatePercentageChange(
57100
- todayVisitorReport[0]?.count ?? 0,
57101
- yesterdayVisitorReport[0]?.count ?? 0
57102
- )
57103
- },
57104
- facilityBooking: {
57105
- count: fFacet.total[0]?.count ?? 0,
57106
- ongoing: fFacet.ongoing[0]?.count ?? 0,
57107
- waitingApproval: fFacet.waitingApproval[0]?.count ?? 0,
57108
- percentage: calculatePercentageChange(
57109
- todayFacilityReport[0]?.count ?? 0,
57110
- yesterdayFacilityReport[0]?.count ?? 0
57111
- )
57112
- }
57113
- };
57114
- return result2;
57115
- }
57116
- if (serviceType === "security_agency" /* SECURITY_AGENCY */) {
57117
- const incidentCollection = db.collection(
57118
- incidents_namespace_collection
57119
- );
57120
- const visitorCollection = db.collection(visitors_namespace_collection);
57121
- const nfcPatrolLogCollection = db.collection("nfc-patrol-logs");
57122
- const [
57123
- workOrderReport2,
57124
- yesterdayWorkOrderReport2,
57125
- todayWorkOrderReport2,
57126
- incidentReport,
57127
- yesterdayIncidentReport,
57128
- todayIncidentReport,
57129
- visitorReport,
57130
- yesterdayVisitorReport,
57131
- todayVisitorReport,
57132
- currentlyOnSiteCount,
57133
- patrolReport,
57134
- yesterdayPatrolReport,
57135
- todayPatrolReport
57136
- ] = await Promise.all([
57137
- workOrderCollection.aggregate([
57138
- {
57139
- $match: {
57140
- site,
57141
- service: "Security",
57142
- createdAt: periodRange,
57143
- status: { $nin: ["completed"] }
57144
- }
57145
- },
57146
- {
57147
- $facet: {
57148
- total: [{ $count: "count" }],
57149
- inProgress: [
57150
- { $match: { status: "in-progress" } },
57151
- { $count: "count" }
57152
- ]
57153
- }
57154
- }
57155
- ]).toArray(),
57156
- workOrderCollection.aggregate([
57157
- {
57158
- $match: {
57159
- site,
57160
- service: "Security",
57161
- createdAt: { $gte: yesterday, $lte: yesterdayEnd },
57162
- status: { $nin: ["completed"] }
57163
- }
57164
- },
57165
- { $count: "count" }
57166
- ]).toArray(),
57167
- workOrderCollection.aggregate([
57168
- {
57169
- $match: {
57170
- site,
57171
- service: "Security",
57172
- createdAt: { $gte: today, $lte: todayEnd },
57173
- status: { $nin: ["completed"] }
57174
- }
57175
- },
57176
- { $count: "count" }
57177
- ]).toArray(),
57178
- incidentCollection.aggregate([
57179
- {
57180
- $match: {
57181
- site,
57182
- status: "pending",
57183
- createdAt: periodRange
57184
- }
57185
- },
57186
- { $count: "count" }
57187
- ]).toArray(),
57188
- incidentCollection.aggregate([
57189
- {
57190
- $match: {
57191
- site,
57192
- status: "pending",
57193
- createdAt: { $gte: yesterday, $lte: yesterdayEnd }
57194
- }
57195
- },
57196
- { $count: "count" }
57197
- ]).toArray(),
57198
- incidentCollection.aggregate([
57199
- {
57200
- $match: {
57201
- site,
57202
- status: "pending",
57203
- createdAt: { $gte: today, $lte: todayEnd }
57204
- }
57205
- },
57206
- { $count: "count" }
57207
- ]).toArray(),
57208
- visitorCollection.aggregate([
57209
- {
57210
- $match: {
57211
- site,
57212
- ...visitorMatchObj,
57213
- createdAt: periodRange,
57214
- status: { $ne: "deleted" }
57215
- }
57216
- },
57217
- { $count: "count" }
57218
- ]).toArray(),
57219
- visitorCollection.aggregate([
57220
- {
57221
- $match: {
57222
- site,
57223
- ...visitorMatchObj,
57224
- createdAt: { $gte: yesterday, $lte: yesterdayEnd },
57225
- status: { $ne: "deleted" }
57226
- }
57227
- },
57228
- { $count: "count" }
57229
- ]).toArray(),
57230
- visitorCollection.aggregate([
57231
- {
57232
- $match: {
57233
- site,
57234
- ...visitorMatchObj,
57235
- createdAt: { $gte: today, $lte: todayEnd },
57236
- status: { $ne: "deleted" }
57237
- }
57238
- },
57239
- { $count: "count" }
57240
- ]).toArray(),
57241
- visitorCollection.countDocuments({
57242
- site,
57243
- ...visitorMatchObj,
57244
- checkIn: { $ne: null },
57245
- checkOut: null,
57246
- status: { $ne: "deleted" }
57247
- }),
57248
- nfcPatrolLogCollection.aggregate([
57249
- {
57250
- $match: {
57251
- site,
57252
- createdAt: periodRange
57253
- }
57254
- },
57255
- {
57256
- $unwind: "$checkPoints"
57257
- },
57258
- {
57259
- $facet: {
57260
- total: [{ $count: "count" }],
57261
- completed: [
57262
- { $match: { "checkPoints.status": "Completed" } },
57263
- { $count: "count" }
57264
- ],
57265
- skipped: [
57266
- { $match: { "checkPoints.status": "Skipped" } },
57267
- { $count: "count" }
57268
- ]
57269
- }
57270
- }
57271
- ]).toArray(),
57272
- nfcPatrolLogCollection.aggregate([
57273
- {
57274
- $match: {
57275
- site,
57276
- createdAt: { $gte: yesterday, $lte: yesterdayEnd }
57277
- }
57278
- },
57279
- {
57280
- $unwind: "$checkPoints"
57281
- },
57282
- {
57283
- $facet: {
57284
- total: [{ $count: "count" }],
57285
- completed: [
57286
- { $match: { "checkPoints.status": "Completed" } },
57287
- { $count: "count" }
57288
- ],
57289
- skipped: [
57290
- { $match: { "checkPoints.status": "Skipped" } },
57291
- { $count: "count" }
57292
- ]
57293
- }
57294
- }
57295
- ]).toArray(),
57296
- nfcPatrolLogCollection.aggregate([
57297
- {
57298
- $match: {
57299
- site,
57300
- createdAt: { $gte: today, $lte: todayEnd }
57301
- }
57302
- },
57303
- {
57304
- $unwind: "$checkPoints"
57305
- },
57306
- {
57307
- $facet: {
57308
- total: [{ $count: "count" }],
57309
- completed: [
57310
- { $match: { "checkPoints.status": "Completed" } },
57311
- { $count: "count" }
57312
- ],
57313
- skipped: [
57314
- { $match: { "checkPoints.status": "Skipped" } },
57315
- { $count: "count" }
57316
- ]
57317
- }
57318
- }
57319
- ]).toArray()
57320
- ]);
57321
- const wFacet2 = workOrderReport2[0] ?? { total: [], inProgress: [] };
57322
- const pFacet = patrolReport[0] ?? {
57323
- total: [],
57324
- completed: [],
57325
- skipped: []
57326
- };
57327
- const totalCheckpoints = pFacet.total[0]?.count ?? 0;
57328
- const completedCheckpoints = pFacet.completed[0]?.count ?? 0;
57329
- const skippedCheckpoints = pFacet.skipped[0]?.count ?? 0;
57330
- const complianceRate = totalCheckpoints > 0 ? Math.round(
57331
- completedCheckpoints / totalCheckpoints * 100 * 100
57332
- ) / 100 : 100;
57333
- const yPatrolFacet = yesterdayPatrolReport[0] ?? {
57334
- total: [],
57335
- completed: []
57336
- };
57337
- const yTotal = yPatrolFacet.total[0]?.count ?? 0;
57338
- const yCompleted = yPatrolFacet.completed[0]?.count ?? 0;
57339
- const yesterdayCompliance = yTotal > 0 ? yCompleted / yTotal * 100 : 0;
57340
- const tPatrolFacet = todayPatrolReport[0] ?? {
57341
- total: [],
57342
- completed: []
57343
- };
57344
- const tTotal = tPatrolFacet.total[0]?.count ?? 0;
57345
- const tCompleted = tPatrolFacet.completed[0]?.count ?? 0;
57346
- const todayCompliance = tTotal > 0 ? tCompleted / tTotal * 100 : 0;
57347
- const result2 = {
57348
- openWorkOrder: {
57349
- count: wFacet2.total[0]?.count ?? 0,
57350
- inProgress: wFacet2.inProgress[0]?.count ?? 0,
57351
- percentage: calculatePercentageChange(
57352
- todayWorkOrderReport2[0]?.count ?? 0,
57353
- yesterdayWorkOrderReport2[0]?.count ?? 0
57354
- )
57355
- },
57356
- openIncidents: {
57357
- count: incidentReport[0]?.count ?? 0,
57358
- highSeverity: 0,
57359
- percentage: calculatePercentageChange(
57360
- todayIncidentReport[0]?.count ?? 0,
57361
- yesterdayIncidentReport[0]?.count ?? 0
57362
- )
57363
- },
57364
- visitors: {
57365
- count: visitorReport[0]?.count ?? 0,
57366
- currentlyOnSite: currentlyOnSiteCount,
57367
- percentage: calculatePercentageChange(
57368
- todayVisitorReport[0]?.count ?? 0,
57369
- yesterdayVisitorReport[0]?.count ?? 0
57370
- )
57371
- },
57372
- patrolCompliance: {
57373
- count: complianceRate,
57374
- missedCheckpoints: skippedCheckpoints,
57375
- missed: skippedCheckpoints,
57376
- percentage: calculatePercentageChange(
57377
- todayCompliance,
57378
- yesterdayCompliance
57379
- )
57380
- }
57381
- };
57382
- return result2;
57383
- }
57384
57544
  const workOrderService = workOrderServiceMap[serviceType] ?? serviceType;
57385
57545
  const [
57386
57546
  workOrderReport,
@@ -57887,13 +58047,8 @@ function useNewDashboardController() {
57887
58047
  try {
57888
58048
  const schema2 = Joi112.object({
57889
58049
  site: Joi112.string().hex().length(24).required(),
57890
- feedbackPeriod: periodField,
57891
- workOrderPeriod: periodField,
57892
- vehiclePeriod: periodField,
57893
- buildingPeriod: periodField,
57894
- visitorPeriod: periodField,
57895
- incidentPeriod: periodField,
57896
- guestPeriod: periodField
58050
+ period: periodField,
58051
+ type: Joi112.string().optional().allow("", null)
57897
58052
  });
57898
58053
  const { error, value } = schema2.validate({
57899
58054
  site: req.params.site,
@@ -57905,25 +58060,11 @@ function useNewDashboardController() {
57905
58060
  next(new BadRequestError183(messages));
57906
58061
  return;
57907
58062
  }
57908
- const {
57909
- site,
57910
- feedbackPeriod,
57911
- workOrderPeriod,
57912
- vehiclePeriod,
57913
- buildingPeriod,
57914
- visitorPeriod,
57915
- incidentPeriod,
57916
- guestPeriod
57917
- } = value;
58063
+ const { site, period, type } = value;
57918
58064
  const data = await _getSecurityDashboard({
57919
58065
  siteId: site,
57920
- feedback: feedbackPeriod,
57921
- workOrder: workOrderPeriod,
57922
- vehicle: vehiclePeriod,
57923
- building: buildingPeriod,
57924
- visitor: visitorPeriod,
57925
- incident: incidentPeriod,
57926
- guest: guestPeriod
58066
+ period,
58067
+ type
57927
58068
  });
57928
58069
  res.status(200).json(data);
57929
58070
  return;
@@ -57937,16 +58078,9 @@ function useNewDashboardController() {
57937
58078
  try {
57938
58079
  const schema2 = Joi112.object({
57939
58080
  site: Joi112.string().hex().length(24).required(),
57940
- feedbackPeriod: periodField,
57941
- workOrderPeriod: periodField,
57942
- vehiclePeriod: periodField,
57943
- buildingPeriod: periodField,
57944
- visitorPeriod: periodField,
57945
- incidentPeriod: periodField,
57946
- sitePeoplePeriod: periodField,
57947
- bulletinBoardPeriod: periodField,
57948
- eventPeriod: periodField,
57949
- facilityBookingPeriod: periodField
58081
+ period: periodField,
58082
+ type: Joi112.string().optional().allow("", null),
58083
+ facility: Joi112.string().hex().optional().allow("", null)
57950
58084
  });
57951
58085
  const { error, value } = schema2.validate({
57952
58086
  site: req.params.site,
@@ -57958,32 +58092,13 @@ function useNewDashboardController() {
57958
58092
  next(new BadRequestError183(messages));
57959
58093
  return;
57960
58094
  }
57961
- const {
58095
+ const { site, period, type, facility } = value;
58096
+ const data = await _getPropertyManagementDashboard(
57962
58097
  site,
57963
- feedbackPeriod,
57964
- workOrderPeriod,
57965
- vehiclePeriod,
57966
- buildingPeriod,
57967
- visitorPeriod,
57968
- incidentPeriod,
57969
- sitePeoplePeriod,
57970
- bulletinBoardPeriod,
57971
- eventPeriod,
57972
- facilityBookingPeriod
57973
- } = value;
57974
- const data = await _getPropertyManagementDashboard({
57975
- siteId: site,
57976
- feedback: feedbackPeriod,
57977
- workOrder: workOrderPeriod,
57978
- vehicle: vehiclePeriod,
57979
- building: buildingPeriod,
57980
- visitor: visitorPeriod,
57981
- incident: incidentPeriod,
57982
- sitePeople: sitePeoplePeriod,
57983
- bulletinBoard: bulletinBoardPeriod,
57984
- event: eventPeriod,
57985
- facilityBooking: facilityBookingPeriod
57986
- });
58098
+ period,
58099
+ type,
58100
+ facility
58101
+ );
57987
58102
  res.status(200).json(data);
57988
58103
  return;
57989
58104
  } catch (error) {
@@ -57997,9 +58112,7 @@ function useNewDashboardController() {
57997
58112
  const validation = Joi112.object({
57998
58113
  site: Joi112.string().hex().required(),
57999
58114
  serviceType: Joi112.string().valid(...Object.values(AppServiceType)).required(),
58000
- period: Joi112.string().valid(...Object.values(Period)).default("today" /* TODAY */),
58001
- type: Joi112.string().optional().allow("", null),
58002
- facility: Joi112.string().hex().optional().allow("", null)
58115
+ period: Joi112.string().valid(...Object.values(Period)).default("today" /* TODAY */)
58003
58116
  });
58004
58117
  const { error } = validation.validate(query);
58005
58118
  if (error) {
@@ -58010,15 +58123,11 @@ function useNewDashboardController() {
58010
58123
  const site = req.params.site ?? "";
58011
58124
  const serviceType = req.params.serviceType;
58012
58125
  const period = req.query.period;
58013
- const type = req.query.type;
58014
- const facility = req.query.facility;
58015
58126
  try {
58016
58127
  const data = await _getServiceDashboard({
58017
58128
  site,
58018
58129
  period,
58019
- serviceType,
58020
- type,
58021
- facility
58130
+ serviceType
58022
58131
  });
58023
58132
  res.json(data);
58024
58133
  return;
@@ -58043,7 +58152,11 @@ function useNewDashboardController() {
58043
58152
  }
58044
58153
  const { site, serviceType, period } = value;
58045
58154
  try {
58046
- const data = await _getServiceWeeklyActivity({ site, serviceType, period });
58155
+ const data = await _getServiceWeeklyActivity({
58156
+ site,
58157
+ serviceType,
58158
+ period
58159
+ });
58047
58160
  res.json(data);
58048
58161
  return;
58049
58162
  } catch (error2) {
@@ -66215,7 +66328,11 @@ import Joi143 from "joi";
66215
66328
  import { BadRequestError as BadRequestError221, InternalServerError as InternalServerError81, useAtlas as useAtlas126 } from "@7365admin1/node-server-utils";
66216
66329
 
66217
66330
  // src/repositories/channel-preloved.repo.ts
66218
- import { InternalServerError as InternalServerError80, useAtlas as useAtlas125 } from "@7365admin1/node-server-utils";
66331
+ import {
66332
+ InternalServerError as InternalServerError80,
66333
+ paginate as paginate63,
66334
+ useAtlas as useAtlas125
66335
+ } from "@7365admin1/node-server-utils";
66219
66336
  import { ObjectId as ObjectId148 } from "mongodb";
66220
66337
 
66221
66338
  // src/models/channel-preloved.model.ts
@@ -66263,6 +66380,7 @@ function useChannelPrelovedRepo() {
66263
66380
  if (!db)
66264
66381
  throw new InternalServerError80("Unable to connect to server.");
66265
66382
  const CHANNEL_COLLECTION = "channel-preloved";
66383
+ const CHAT_COLLECTION = "chat-preloved";
66266
66384
  const collection = db.collection(CHANNEL_COLLECTION);
66267
66385
  async function add(value, session) {
66268
66386
  try {
@@ -66281,7 +66399,85 @@ function useChannelPrelovedRepo() {
66281
66399
  };
66282
66400
  return collection.findOne(query, { session });
66283
66401
  }
66284
- return { add, getByParticipants };
66402
+ async function getChannelMessages(channelId, page = 1, limit = 10, isLoadMore = false, lastMessageId = null) {
66403
+ const chatCollection = db.collection(CHAT_COLLECTION);
66404
+ const normalizedPage = page > 0 ? page - 1 : 0;
66405
+ const normalizedLimit = limit || 10;
66406
+ const matchCriteria = {
66407
+ channelId: new ObjectId148(channelId),
66408
+ deletedAt: null
66409
+ };
66410
+ if (isLoadMore && lastMessageId) {
66411
+ matchCriteria._id = { $lt: new ObjectId148(lastMessageId) };
66412
+ }
66413
+ try {
66414
+ const result = await chatCollection.aggregate([
66415
+ { $match: matchCriteria },
66416
+ {
66417
+ $lookup: {
66418
+ from: "users",
66419
+ localField: "senderId",
66420
+ foreignField: "_id",
66421
+ pipeline: [
66422
+ {
66423
+ $project: {
66424
+ name: 1,
66425
+ profile: 1,
66426
+ type: 1
66427
+ }
66428
+ }
66429
+ ],
66430
+ as: "senderId"
66431
+ }
66432
+ },
66433
+ { $unwind: { path: "$senderId", preserveNullAndEmptyArrays: true } },
66434
+ {
66435
+ $lookup: {
66436
+ from: "bid-preloved",
66437
+ localField: "bidId",
66438
+ foreignField: "_id",
66439
+ pipeline: [
66440
+ { $project: { price: 1, message: 1, status: 1, type: 1 } }
66441
+ ],
66442
+ as: "bidId"
66443
+ }
66444
+ },
66445
+ { $unwind: { path: "$bidId", preserveNullAndEmptyArrays: true } },
66446
+ {
66447
+ $lookup: {
66448
+ from: "post-preloved",
66449
+ localField: "postId",
66450
+ foreignField: "_id",
66451
+ pipeline: [{ $project: { title: 1, status: 1, reserverId: 1 } }],
66452
+ as: "postDetails"
66453
+ }
66454
+ },
66455
+ {
66456
+ $unwind: {
66457
+ path: "$postDetails",
66458
+ preserveNullAndEmptyArrays: true
66459
+ }
66460
+ },
66461
+ { $sort: { createdAt: -1 } },
66462
+ {
66463
+ $facet: {
66464
+ totalCount: [{ $count: "count" }],
66465
+ items: [
66466
+ { $skip: normalizedPage * normalizedLimit },
66467
+ { $limit: normalizedLimit }
66468
+ ]
66469
+ }
66470
+ }
66471
+ ]).toArray();
66472
+ const totalCount = result[0].totalCount[0]?.count ?? 0;
66473
+ const items = result[0].items;
66474
+ items.reverse();
66475
+ return paginate63(items, normalizedPage, normalizedLimit, totalCount);
66476
+ } catch (error) {
66477
+ throw error;
66478
+ }
66479
+ }
66480
+ return { add, getByParticipants, getChannelMessages };
66285
66481
  }
66286
66482
 
66287
66483
  // src/services/chat-preloved.service.ts
@@ -66397,8 +66593,9 @@ function useChatPrelovedController() {
66397
66593
 
66398
66594
  // src/controllers/channel-preloved.controller.ts
66399
66595
  import { BadRequestError as BadRequestError223, logger as logger193 } from "@7365admin1/node-server-utils";
66596
+ import Joi144 from "joi";
66400
66597
  function useChannelPrelovedController() {
66401
- const { add: _add } = useChannelPrelovedRepo();
66598
+ const { add: _add, getChannelMessages: _getChannelMessages } = useChannelPrelovedRepo();
66402
66599
  async function add(req, res, next) {
66403
66600
  const { error, value } = schemaChannelPreloved.validate(req.body, {
66404
66601
  abortEarly: false
@@ -66417,11 +66614,51 @@ function useChannelPrelovedController() {
66417
66614
  next(error2);
66418
66615
  }
66419
66616
  }
66420
- return { add };
66617
+ async function getChannelMessages(req, res, next) {
66618
+ const paramsSchema = Joi144.object({
66619
+ id: Joi144.string().hex().length(24).required()
66620
+ });
66621
+ const querySchema = Joi144.object({
66622
+ page: Joi144.number().integer().min(1).default(1),
66623
+ limit: Joi144.number().integer().min(1).max(100).default(10),
66624
+ isLoadMore: Joi144.boolean().default(false),
66625
+ lastMessageId: Joi144.string().hex().length(24).optional().allow("", null)
66626
+ });
66627
+ const { error: paramError, value: params } = paramsSchema.validate(
66628
+ req.params
66629
+ );
66630
+ if (paramError) {
66631
+ logger193.log({ level: "error", message: paramError.message });
66632
+ next(new BadRequestError223(paramError.message));
66633
+ return;
66634
+ }
66635
+ const { error: queryError, value: query } = querySchema.validate(
66636
+ req.query
66637
+ );
66638
+ if (queryError) {
66639
+ logger193.log({ level: "error", message: queryError.message });
66640
+ next(new BadRequestError223(queryError.message));
66641
+ return;
66642
+ }
66643
+ try {
66644
+ const data = await _getChannelMessages(
66645
+ params.id,
66646
+ query.page,
66647
+ query.limit,
66648
+ query.isLoadMore,
66649
+ query.lastMessageId || null
66650
+ );
66651
+ res.status(200).json(data);
66652
+ } catch (error) {
66653
+ logger193.log({ level: "error", message: error.message });
66654
+ next(error);
66655
+ }
66656
+ }
66657
+ return { add, getChannelMessages };
66421
66658
  }
66422
66659
 
66423
66660
  // src/models/online-forms-v2.model.ts
66424
- import Joi144 from "joi";
66661
+ import Joi145 from "joi";
66425
66662
  import { ObjectId as ObjectId149 } from "mongodb";
66426
66663
  var FormEntryStatus = /* @__PURE__ */ ((FormEntryStatus2) => {
66427
66664
  FormEntryStatus2["ACTIVE"] = "active";
@@ -66429,49 +66666,49 @@ var FormEntryStatus = /* @__PURE__ */ ((FormEntryStatus2) => {
66429
66666
  FormEntryStatus2["DELETED"] = "deleted";
66430
66667
  return FormEntryStatus2;
66431
66668
  })(FormEntryStatus || {});
66432
- var schemaFormEntry = Joi144.object({
66433
- _id: Joi144.string().hex().optional().allow("", null),
66434
- formType: Joi144.string().required(),
66435
- block: Joi144.string().optional().allow(null, ""),
66436
- level: Joi144.string().optional().allow(null, ""),
66437
- unit: Joi144.string().optional().allow(null, ""),
66438
- name: Joi144.string().optional().allow(null, ""),
66439
- phoneNumber: Joi144.string().optional().allow(null, ""),
66440
- createdBy: Joi144.string().required(),
66441
- fields: Joi144.object().pattern(
66442
- Joi144.string(),
66443
- Joi144.alternatives().try(
66444
- Joi144.string(),
66445
- Joi144.number(),
66446
- Joi144.boolean(),
66447
- Joi144.valid(null)
66669
+ var schemaFormEntry = Joi145.object({
66670
+ _id: Joi145.string().hex().optional().allow("", null),
66671
+ formType: Joi145.string().required(),
66672
+ block: Joi145.string().optional().allow(null, ""),
66673
+ level: Joi145.string().optional().allow(null, ""),
66674
+ unit: Joi145.string().optional().allow(null, ""),
66675
+ name: Joi145.string().optional().allow(null, ""),
66676
+ phoneNumber: Joi145.string().optional().allow(null, ""),
66677
+ createdBy: Joi145.string().required(),
66678
+ fields: Joi145.object().pattern(
66679
+ Joi145.string(),
66680
+ Joi145.alternatives().try(
66681
+ Joi145.string(),
66682
+ Joi145.number(),
66683
+ Joi145.boolean(),
66684
+ Joi145.valid(null)
66448
66685
  )
66449
66686
  ).required(),
66450
- status: Joi144.string().optional().allow("", null),
66451
- org: Joi144.string().hex().optional().allow("", null),
66452
- site: Joi144.string().hex().optional().allow("", null),
66453
- createdAt: Joi144.date().optional().allow("", null),
66454
- updatedAt: Joi144.date().optional().allow("", null),
66455
- deletedAt: Joi144.date().optional().allow("", null)
66687
+ status: Joi145.string().optional().allow("", null),
66688
+ org: Joi145.string().hex().optional().allow("", null),
66689
+ site: Joi145.string().hex().optional().allow("", null),
66690
+ createdAt: Joi145.date().optional().allow("", null),
66691
+ updatedAt: Joi145.date().optional().allow("", null),
66692
+ deletedAt: Joi145.date().optional().allow("", null)
66456
66693
  });
66457
- var schemaUpdateFormEntry = Joi144.object({
66458
- _id: Joi144.string().hex().required(),
66459
- formType: Joi144.string().optional().allow("", null),
66460
- block: Joi144.string().optional().allow(null, ""),
66461
- level: Joi144.string().optional().allow(null, ""),
66462
- unit: Joi144.string().optional().allow(null, ""),
66463
- fields: Joi144.object().pattern(
66464
- Joi144.string(),
66465
- Joi144.alternatives().try(
66466
- Joi144.string(),
66467
- Joi144.number(),
66468
- Joi144.boolean(),
66469
- Joi144.valid(null)
66694
+ var schemaUpdateFormEntry = Joi145.object({
66695
+ _id: Joi145.string().hex().required(),
66696
+ formType: Joi145.string().optional().allow("", null),
66697
+ block: Joi145.string().optional().allow(null, ""),
66698
+ level: Joi145.string().optional().allow(null, ""),
66699
+ unit: Joi145.string().optional().allow(null, ""),
66700
+ fields: Joi145.object().pattern(
66701
+ Joi145.string(),
66702
+ Joi145.alternatives().try(
66703
+ Joi145.string(),
66704
+ Joi145.number(),
66705
+ Joi145.boolean(),
66706
+ Joi145.valid(null)
66470
66707
  )
66471
66708
  ).optional(),
66472
- status: Joi144.string().optional().allow("", null),
66473
- updatedAt: Joi144.date().optional().allow("", null),
66474
- deletedAt: Joi144.date().optional().allow("", null)
66709
+ status: Joi145.string().optional().allow("", null),
66710
+ updatedAt: Joi145.date().optional().allow("", null),
66711
+ deletedAt: Joi145.date().optional().allow("", null)
66475
66712
  });
66476
66713
  function MFormEntry(value) {
66477
66714
  const { error } = schemaFormEntry.validate(value);
@@ -66516,34 +66753,34 @@ function MFormEntry(value) {
66516
66753
  deletedAt: value.deletedAt ?? null
66517
66754
  };
66518
66755
  }
66519
- var residentFormEntry = Joi144.object({
66520
- _id: Joi144.string().hex().optional().allow("", null),
66521
- typeOfForm: Joi144.string().optional().allow("", null),
66522
- unitNumber: Joi144.string().optional().allow(null, ""),
66523
- fields: Joi144.object().pattern(
66524
- Joi144.string(),
66525
- Joi144.alternatives().try(
66526
- Joi144.string(),
66527
- Joi144.number(),
66528
- Joi144.boolean(),
66529
- Joi144.valid(null)
66756
+ var residentFormEntry = Joi145.object({
66757
+ _id: Joi145.string().hex().optional().allow("", null),
66758
+ typeOfForm: Joi145.string().optional().allow("", null),
66759
+ unitNumber: Joi145.string().optional().allow(null, ""),
66760
+ fields: Joi145.object().pattern(
66761
+ Joi145.string(),
66762
+ Joi145.alternatives().try(
66763
+ Joi145.string(),
66764
+ Joi145.number(),
66765
+ Joi145.boolean(),
66766
+ Joi145.valid(null)
66530
66767
  )
66531
66768
  ).optional().allow(null, ""),
66532
- status: Joi144.string().optional().allow("", null),
66533
- org: Joi144.string().hex().optional().allow("", null),
66534
- site: Joi144.string().hex().optional().allow("", null),
66535
- userId: Joi144.string().hex().optional().allow("", null),
66536
- createdAt: Joi144.date().optional().allow("", null),
66537
- updatedAt: Joi144.date().optional().allow("", null),
66538
- deletedAt: Joi144.date().optional().allow("", null),
66539
- remarks: Joi144.string().optional().allow("", null),
66540
- managementValues: Joi144.object().pattern(
66541
- Joi144.string(),
66542
- Joi144.alternatives().try(
66543
- Joi144.string(),
66544
- Joi144.number(),
66545
- Joi144.boolean(),
66546
- Joi144.valid(null)
66769
+ status: Joi145.string().optional().allow("", null),
66770
+ org: Joi145.string().hex().optional().allow("", null),
66771
+ site: Joi145.string().hex().optional().allow("", null),
66772
+ userId: Joi145.string().hex().optional().allow("", null),
66773
+ createdAt: Joi145.date().optional().allow("", null),
66774
+ updatedAt: Joi145.date().optional().allow("", null),
66775
+ deletedAt: Joi145.date().optional().allow("", null),
66776
+ remarks: Joi145.string().optional().allow("", null),
66777
+ managementValues: Joi145.object().pattern(
66778
+ Joi145.string(),
66779
+ Joi145.alternatives().try(
66780
+ Joi145.string(),
66781
+ Joi145.number(),
66782
+ Joi145.boolean(),
66783
+ Joi145.valid(null)
66547
66784
  )
66548
66785
  ).optional().allow(null, "")
66549
66786
  });
@@ -66555,7 +66792,7 @@ import {
66555
66792
  logger as logger194,
66556
66793
  makeCacheKey as makeCacheKey65,
66557
66794
  NotFoundError as NotFoundError61,
66558
- paginate as paginate63,
66795
+ paginate as paginate64,
66559
66796
  useAtlas as useAtlas127,
66560
66797
  useCache as useCache69
66561
66798
  } from "@7365admin1/node-server-utils";
@@ -66653,7 +66890,7 @@ function useFormEntryRepo() {
66653
66890
  { $limit: limit }
66654
66891
  ]).toArray();
66655
66892
  const length = await collection.countDocuments(query);
66656
- const data = paginate63(items, page, limit, length);
66893
+ const data = paginate64(items, page, limit, length);
66657
66894
  setCache(cacheKey, data, 15 * 60).then(() => {
66658
66895
  logger194.info(`Cache set for key: ${cacheKey}`);
66659
66896
  }).catch((err) => {
@@ -66813,7 +67050,7 @@ function useFormEntryRepo() {
66813
67050
 
66814
67051
  // src/controllers/online-forms-v2.controller.ts
66815
67052
  import { BadRequestError as BadRequestError225, logger as logger195 } from "@7365admin1/node-server-utils";
66816
- import Joi145 from "joi";
67053
+ import Joi146 from "joi";
66817
67054
  import ExcelJS3 from "exceljs";
66818
67055
  import fs6 from "fs";
66819
67056
  function useFormEntryController() {
@@ -66889,13 +67126,13 @@ function useFormEntryController() {
66889
67126
  }
66890
67127
  async function getAll(req, res, next) {
66891
67128
  try {
66892
- const schema2 = Joi145.object({
66893
- search: Joi145.string().optional().allow("", null),
66894
- page: Joi145.number().integer().min(1).allow("", null).default(1),
66895
- limit: Joi145.number().integer().min(1).max(100).allow("", null).default(10),
66896
- status: Joi145.string().optional().allow(null, ""),
66897
- org: Joi145.string().hex().optional().allow("", null),
66898
- site: Joi145.string().hex().optional().allow("", null)
67129
+ const schema2 = Joi146.object({
67130
+ search: Joi146.string().optional().allow("", null),
67131
+ page: Joi146.number().integer().min(1).allow("", null).default(1),
67132
+ limit: Joi146.number().integer().min(1).max(100).allow("", null).default(10),
67133
+ status: Joi146.string().optional().allow(null, ""),
67134
+ org: Joi146.string().hex().optional().allow("", null),
67135
+ site: Joi146.string().hex().optional().allow("", null)
66899
67136
  });
66900
67137
  const { error, value } = schema2.validate(req.query);
66901
67138
  if (error) {
@@ -66916,8 +67153,8 @@ function useFormEntryController() {
66916
67153
  }
66917
67154
  async function getFormEntryById(req, res, next) {
66918
67155
  try {
66919
- const schema2 = Joi145.object({
66920
- _id: Joi145.string().hex().length(24).required()
67156
+ const schema2 = Joi146.object({
67157
+ _id: Joi146.string().hex().length(24).required()
66921
67158
  });
66922
67159
  const { error, value } = schema2.validate({ _id: req.params.id });
66923
67160
  if (error) {
@@ -66960,7 +67197,7 @@ function useFormEntryController() {
66960
67197
  }
66961
67198
  async function deleteFormEntryById(req, res, next) {
66962
67199
  try {
66963
- const validation = Joi145.string().hex().required();
67200
+ const validation = Joi146.string().hex().required();
66964
67201
  const _id = req.params.id;
66965
67202
  const { error } = validation.validate(_id);
66966
67203
  if (error) {
@@ -67027,10 +67264,10 @@ function useFormEntryController() {
67027
67264
  async function residentForm(req, res, next) {
67028
67265
  try {
67029
67266
  const { site, userId, org } = req.query;
67030
- const residentFormPayload = Joi145.object({
67031
- org: Joi145.string().hex().required(),
67032
- site: Joi145.string().hex().required(),
67033
- userId: Joi145.string().hex().required()
67267
+ const residentFormPayload = Joi146.object({
67268
+ org: Joi146.string().hex().required(),
67269
+ site: Joi146.string().hex().required(),
67270
+ userId: Joi146.string().hex().required()
67034
67271
  });
67035
67272
  const { error } = residentFormPayload.validate({ site, userId, org }, { abortEarly: true });
67036
67273
  if (error) {
@@ -67099,7 +67336,7 @@ function useBuildingLevelService() {
67099
67336
 
67100
67337
  // src/controllers/building-level.controller.ts
67101
67338
  import { BadRequestError as BadRequestError226, logger as logger196 } from "@7365admin1/node-server-utils";
67102
- import Joi146 from "joi";
67339
+ import Joi147 from "joi";
67103
67340
  function useBuildingLevelController() {
67104
67341
  const { add: _add, updateLevelById: _updateLevelById } = useBuildingLevelService();
67105
67342
  const {
@@ -67128,12 +67365,12 @@ function useBuildingLevelController() {
67128
67365
  }
67129
67366
  async function getAll(req, res, next) {
67130
67367
  try {
67131
- const validation = Joi146.object({
67132
- page: Joi146.number().min(1).optional().default(1),
67133
- limit: Joi146.number().min(1).optional().default(20),
67134
- search: Joi146.string().optional().allow("", null),
67135
- site: Joi146.string().hex().length(24).optional().allow("", null),
67136
- status: Joi146.string().valid(...Object.values(BuildingLevelStatus)).default("active" /* ACTIVE */)
67368
+ const validation = Joi147.object({
67369
+ page: Joi147.number().min(1).optional().default(1),
67370
+ limit: Joi147.number().min(1).optional().default(20),
67371
+ search: Joi147.string().optional().allow("", null),
67372
+ site: Joi147.string().hex().length(24).optional().allow("", null),
67373
+ status: Joi147.string().valid(...Object.values(BuildingLevelStatus)).default("active" /* ACTIVE */)
67137
67374
  });
67138
67375
  const { error, value } = validation.validate(req.query, {
67139
67376
  abortEarly: false
@@ -67160,8 +67397,8 @@ function useBuildingLevelController() {
67160
67397
  }
67161
67398
  async function getById(req, res, next) {
67162
67399
  try {
67163
- const schema2 = Joi146.object({
67164
- id: Joi146.string().hex().length(24).required()
67400
+ const schema2 = Joi147.object({
67401
+ id: Joi147.string().hex().length(24).required()
67165
67402
  });
67166
67403
  const { error, value } = schema2.validate({ id: req.params.id });
67167
67404
  if (error) {
@@ -67199,8 +67436,8 @@ function useBuildingLevelController() {
67199
67436
  }
67200
67437
  async function deleteById(req, res, next) {
67201
67438
  try {
67202
- const schema2 = Joi146.object({
67203
- id: Joi146.string().hex().required()
67439
+ const schema2 = Joi147.object({
67440
+ id: Joi147.string().hex().required()
67204
67441
  });
67205
67442
  const { error, value } = schema2.validate({ id: req.params.id });
67206
67443
  if (error) {
@@ -67219,11 +67456,11 @@ function useBuildingLevelController() {
67219
67456
  }
67220
67457
  async function batchUpdateByIds(req, res, next) {
67221
67458
  try {
67222
- const schema2 = Joi146.array().items(
67223
- Joi146.object({
67224
- _id: Joi146.string().hex().length(24).required(),
67225
- value: Joi146.object({
67226
- name: Joi146.string().optional().allow("", null)
67459
+ const schema2 = Joi147.array().items(
67460
+ Joi147.object({
67461
+ _id: Joi147.string().hex().length(24).required(),
67462
+ value: Joi147.object({
67463
+ name: Joi147.string().optional().allow("", null)
67227
67464
  }).required()
67228
67465
  })
67229
67466
  );
@@ -67246,9 +67483,9 @@ function useBuildingLevelController() {
67246
67483
  }
67247
67484
  async function getBuildingLevelList(req, res, next) {
67248
67485
  try {
67249
- const schema2 = Joi146.object({
67250
- site: Joi146.string().hex().length(24).required(),
67251
- block: Joi146.string().hex().length(24).required()
67486
+ const schema2 = Joi147.object({
67487
+ site: Joi147.string().hex().length(24).required(),
67488
+ block: Joi147.string().hex().length(24).required()
67252
67489
  });
67253
67490
  const { error, value } = schema2.validate({
67254
67491
  site: req.params.siteId,