@7365admin1/core 3.6.0 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -18547,7 +18547,7 @@ function useServiceProviderRepo() {
18547
18547
  }) {
18548
18548
  page = page > 0 ? page - 1 : 0;
18549
18549
  const query = { status };
18550
- const cacheOptions = { status };
18550
+ const cacheOptions = { status, page, limit };
18551
18551
  sort = Object.keys(sort).length > 0 ? sort : { _id: -1 };
18552
18552
  cacheOptions.sort = JSON.stringify(sort);
18553
18553
  if (search) {
@@ -21385,6 +21385,10 @@ function useVisitorTransactionRepo() {
21385
21385
  const data = paginate17(items, page, limit, totalCount);
21386
21386
  return data;
21387
21387
  } catch (error) {
21388
+ logger48.error("Error in getAll visitor transaction repo", {
21389
+ message: error.message,
21390
+ stack: error.stack
21391
+ });
21388
21392
  throw error;
21389
21393
  }
21390
21394
  }
@@ -21457,6 +21461,22 @@ function useVisitorTransactionRepo() {
21457
21461
  ]).toArray();
21458
21462
  return result;
21459
21463
  } catch (error) {
21464
+ if (error instanceof Error) {
21465
+ logger48.error(
21466
+ "Error in getVisitorTransactionById visitor transaction repo",
21467
+ {
21468
+ message: error.message,
21469
+ stack: error.stack
21470
+ }
21471
+ );
21472
+ } else {
21473
+ logger48.error(
21474
+ "Unknown error in getVisitorTransactionById visitor transaction repo",
21475
+ {
21476
+ error
21477
+ }
21478
+ );
21479
+ }
21460
21480
  throw error;
21461
21481
  }
21462
21482
  }
@@ -21471,9 +21491,19 @@ function useVisitorTransactionRepo() {
21471
21491
  const data = await collection.findOne(query);
21472
21492
  return data;
21473
21493
  } catch (error) {
21474
- throw new InternalServerError24(
21475
- "Failed to fetch visitor transaction by plate number."
21476
- );
21494
+ if (error instanceof Error) {
21495
+ logger48.error("Error in getOpenByPlateNumber visitor transaction repo", {
21496
+ message: error.message,
21497
+ stack: error.stack
21498
+ });
21499
+ } else {
21500
+ logger48.error(
21501
+ "Unknown error in getOpenByPlateNumber visitor transaction repo",
21502
+ {
21503
+ error
21504
+ }
21505
+ );
21506
+ }
21477
21507
  }
21478
21508
  }
21479
21509
  async function updateById(_id, value, session, isManualCheckOut = true) {
@@ -25762,7 +25792,6 @@ function useBuildingUnitRepo() {
25762
25792
  const buildingCollection = await db?.collection("buildings").findOne({ _id: toObjectId11(block) });
25763
25793
  const blockNumber = buildingCollection?.block;
25764
25794
  query.block = blockNumber !== void 0 ? blockNumber : block;
25765
- console.log("Query for getBuildingUnits:", query);
25766
25795
  try {
25767
25796
  const data = await collection.aggregate([{ $match: query }, { $project: { name: 1 } }]).toArray();
25768
25797
  setCache(cacheKey, data, 15 * 60).then(() => {
@@ -25819,6 +25848,20 @@ function useBuildingUnitRepo() {
25819
25848
  try {
25820
25849
  const data = await collection.aggregate([
25821
25850
  { $match: query },
25851
+ {
25852
+ $lookup: {
25853
+ from: "buildings",
25854
+ localField: "building",
25855
+ foreignField: "_id",
25856
+ pipeline: [{ $project: { _id: 0, name: 1 } }],
25857
+ as: "_blockData"
25858
+ }
25859
+ },
25860
+ {
25861
+ $unwind: { path: "$_blockData", preserveNullAndEmptyArrays: true }
25862
+ },
25863
+ { $addFields: { blockName: { $ifNull: ["$_blockData.name", ""] } } },
25864
+ { $unset: "_blockData" },
25822
25865
  {
25823
25866
  $lookup: {
25824
25867
  from: "building-levels",
@@ -25828,7 +25871,9 @@ function useBuildingUnitRepo() {
25828
25871
  as: "_levelData"
25829
25872
  }
25830
25873
  },
25831
- { $unwind: { path: "$_levelData", preserveNullAndEmptyArrays: true } },
25874
+ {
25875
+ $unwind: { path: "$_levelData", preserveNullAndEmptyArrays: true }
25876
+ },
25832
25877
  { $addFields: { levelName: { $ifNull: ["$_levelData.name", ""] } } },
25833
25878
  { $unset: "_levelData" }
25834
25879
  ]).toArray();
@@ -25934,7 +25979,6 @@ function useBuildingUnitRepo() {
25934
25979
  level,
25935
25980
  status: "active"
25936
25981
  };
25937
- console.log(query);
25938
25982
  const result = await collection.findOne(query);
25939
25983
  setCache(cacheKey, result, 300).then(() => {
25940
25984
  logger54.log({
@@ -44025,14 +44069,14 @@ function useSiteUnitBillingService() {
44025
44069
  billing_item.units,
44026
44070
  billing_item.site?.toString() || ""
44027
44071
  );
44028
- if (unitsWithOwner?.length) {
44072
+ if (unitsWithOwner?.length > 0) {
44029
44073
  const buildUnitBilling = (unit) => ({
44030
- site: billing_item.site,
44031
- org: billing_item.org,
44074
+ site: billing_item.site.toString(),
44075
+ org: billing_item.org.toString(),
44032
44076
  billItem: billing_item._id,
44033
44077
  billName: billing_item.name,
44034
- unitId: unit._id,
44035
- unit: unit.block + " / " + unit.level + " / " + unit.name,
44078
+ unitId: unit._id.toString(),
44079
+ unit: unit.blockName + " / " + unit.levelName + " / " + unit.name,
44036
44080
  unitOwner: unit.ownerName,
44037
44081
  email: unit.email,
44038
44082
  contactNumber: unit.contact,
@@ -44058,6 +44102,7 @@ function useSiteUnitBillingService() {
44058
44102
  );
44059
44103
  await session.commitTransaction();
44060
44104
  } catch (error) {
44105
+ console.log("BILLING ERROR:", error.message, error);
44061
44106
  logger122.log({
44062
44107
  level: "error",
44063
44108
  message: `Failed to proccess cron billing: ${error.message}`
@@ -56583,6 +56628,7 @@ function useNewDashboardRepo() {
56583
56628
  const area_checklist_namespace_collection = "site.cleaning.schedule.areas";
56584
56629
  const supply_namespace_collection = "site.supplies";
56585
56630
  const work_order_namespace_collection = "work-orders2";
56631
+ const facility_bookings_namespace_collection2 = "facilities-booking";
56586
56632
  const areaChecklistCollection = db.collection(
56587
56633
  area_checklist_namespace_collection
56588
56634
  );
@@ -56598,171 +56644,724 @@ function useNewDashboardRepo() {
56598
56644
  pest_control_services: "Pest Control",
56599
56645
  pool_maintenance_services: "Pool Maintenance"
56600
56646
  };
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: [
56647
+ function formatEndDate(date) {
56648
+ if (typeof date === "string") {
56649
+ const dateWithoutTimezone = date.replace(/\s*\+\d{2}:\d{2}$/, "");
56650
+ date = new Date(dateWithoutTimezone);
56651
+ }
56652
+ const singaporeMoment = moment2.tz(date, "Asia/Singapore");
56653
+ singaporeMoment.set({
56654
+ hour: 23,
56655
+ minute: 59,
56656
+ second: 59,
56657
+ millisecond: 999
56658
+ });
56659
+ return singaporeMoment.toDate();
56660
+ }
56661
+ function getDateRange(p) {
56662
+ const start = /* @__PURE__ */ new Date();
56663
+ start.setHours(0, 0, 0, 0);
56664
+ if (p === "today") {
56665
+ return { $gte: start, $lte: formatEndDate(start) };
56666
+ }
56667
+ const days = p === "thisWeek" ? 7 : 30;
56668
+ const rangeStart = /* @__PURE__ */ new Date();
56669
+ rangeStart.setDate(start.getDate() - days);
56670
+ rangeStart.setHours(0, 0, 0, 0);
56671
+ return { $gte: rangeStart, $lte: formatEndDate(/* @__PURE__ */ new Date()) };
56672
+ }
56673
+ const calculatePercentageChange = (currentCount, previousCount) => {
56674
+ if (previousCount === 0) {
56675
+ return currentCount > 0 ? 100 : 0;
56676
+ }
56677
+ return Math.round((currentCount - previousCount) / previousCount * 100 * 100) / 100;
56678
+ };
56679
+ async function getSecurityDashboard({
56680
+ siteId = "",
56681
+ period = "today" /* TODAY */,
56682
+ type
56683
+ }) {
56684
+ const siteIdObj = toObjectId16(siteId);
56685
+ const visitorMatchObj = {};
56686
+ if (type) {
56687
+ visitorMatchObj.type = type;
56688
+ }
56689
+ const today = /* @__PURE__ */ new Date();
56690
+ today.setHours(0, 0, 0, 0);
56691
+ const yesterday = /* @__PURE__ */ new Date();
56692
+ yesterday.setDate(today.getDate() - 1);
56693
+ yesterday.setHours(0, 0, 0, 0);
56694
+ const yesterdayEnd = new Date(yesterday);
56695
+ yesterdayEnd.setHours(23, 59, 59, 999);
56696
+ const todayEnd = formatEndDate(/* @__PURE__ */ new Date());
56697
+ const periodRange = getDateRange(period);
56698
+ const incidentCollection = db.collection(incidents_namespace_collection);
56699
+ const visitorCollection = db.collection(visitors_namespace_collection);
56700
+ const nfcPatrolLogCollection = db.collection("nfc-patrol-logs");
56701
+ const [
56702
+ workOrderReport,
56703
+ yesterdayWorkOrderReport,
56704
+ todayWorkOrderReport,
56705
+ incidentReport,
56706
+ yesterdayIncidentReport,
56707
+ todayIncidentReport,
56708
+ visitorReport,
56709
+ yesterdayVisitorReport,
56710
+ todayVisitorReport,
56711
+ currentlyOnSiteCount,
56712
+ patrolReport,
56713
+ yesterdayPatrolReport,
56714
+ todayPatrolReport
56715
+ ] = await Promise.all([
56716
+ workOrderCollection.aggregate([
56608
56717
  {
56609
- createdAt: {
56610
- $gte: range.current.start,
56611
- $lte: range.current.end
56718
+ $match: {
56719
+ site: { $in: [siteIdObj, siteId] },
56720
+ service: "Security",
56721
+ createdAt: periodRange,
56722
+ status: { $nin: ["completed"] }
56612
56723
  }
56613
56724
  },
56614
56725
  {
56615
- createdAt: {
56616
- $gte: new Date(range.current.start),
56617
- $lte: new Date(range.current.end)
56726
+ $facet: {
56727
+ total: [{ $count: "count" }],
56728
+ inProgress: [
56729
+ { $match: { status: "in-progress" } },
56730
+ { $count: "count" }
56731
+ ]
56618
56732
  }
56619
56733
  }
56620
- ]
56621
- });
56622
- const previous = await collection.countDocuments({
56623
- site,
56624
- $or: [
56734
+ ]).toArray(),
56735
+ workOrderCollection.aggregate([
56736
+ {
56737
+ $match: {
56738
+ site: { $in: [siteIdObj, siteId] },
56739
+ service: "Security",
56740
+ createdAt: { $gte: yesterday, $lte: yesterdayEnd },
56741
+ status: { $nin: ["completed"] }
56742
+ }
56743
+ },
56744
+ { $count: "count" }
56745
+ ]).toArray(),
56746
+ workOrderCollection.aggregate([
56747
+ {
56748
+ $match: {
56749
+ site: { $in: [siteIdObj, siteId] },
56750
+ service: "Security",
56751
+ createdAt: { $gte: today, $lte: todayEnd },
56752
+ status: { $nin: ["completed"] }
56753
+ }
56754
+ },
56755
+ { $count: "count" }
56756
+ ]).toArray(),
56757
+ incidentCollection.aggregate([
56758
+ {
56759
+ $match: {
56760
+ site: { $in: [siteIdObj, siteId] },
56761
+ status: { $in: ["pending", "Pending"] },
56762
+ createdAt: periodRange
56763
+ }
56764
+ },
56765
+ { $count: "count" }
56766
+ ]).toArray(),
56767
+ incidentCollection.aggregate([
56768
+ {
56769
+ $match: {
56770
+ site: { $in: [siteIdObj, siteId] },
56771
+ status: { $in: ["pending", "Pending"] },
56772
+ createdAt: { $gte: yesterday, $lte: yesterdayEnd }
56773
+ }
56774
+ },
56775
+ { $count: "count" }
56776
+ ]).toArray(),
56777
+ incidentCollection.aggregate([
56778
+ {
56779
+ $match: {
56780
+ site: { $in: [siteIdObj, siteId] },
56781
+ status: { $in: ["pending", "Pending"] },
56782
+ createdAt: { $gte: today, $lte: todayEnd }
56783
+ }
56784
+ },
56785
+ { $count: "count" }
56786
+ ]).toArray(),
56787
+ visitorCollection.aggregate([
56788
+ {
56789
+ $match: {
56790
+ site: { $in: [siteIdObj, siteId] },
56791
+ ...visitorMatchObj,
56792
+ createdAt: periodRange,
56793
+ status: { $ne: "deleted" }
56794
+ }
56795
+ },
56796
+ { $count: "count" }
56797
+ ]).toArray(),
56798
+ visitorCollection.aggregate([
56625
56799
  {
56626
- createdAt: {
56627
- $gte: range.previous.start,
56628
- $lte: range.previous.end
56800
+ $match: {
56801
+ site: { $in: [siteIdObj, siteId] },
56802
+ ...visitorMatchObj,
56803
+ createdAt: { $gte: yesterday, $lte: yesterdayEnd },
56804
+ status: { $ne: "deleted" }
56805
+ }
56806
+ },
56807
+ { $count: "count" }
56808
+ ]).toArray(),
56809
+ visitorCollection.aggregate([
56810
+ {
56811
+ $match: {
56812
+ site: { $in: [siteIdObj, siteId] },
56813
+ ...visitorMatchObj,
56814
+ createdAt: { $gte: today, $lte: todayEnd },
56815
+ status: { $ne: "deleted" }
56816
+ }
56817
+ },
56818
+ { $count: "count" }
56819
+ ]).toArray(),
56820
+ visitorCollection.countDocuments({
56821
+ site: { $in: [siteIdObj, siteId] },
56822
+ ...visitorMatchObj,
56823
+ checkIn: { $ne: null },
56824
+ checkOut: null,
56825
+ status: { $ne: "deleted" }
56826
+ }),
56827
+ nfcPatrolLogCollection.aggregate([
56828
+ {
56829
+ $match: {
56830
+ site: { $in: [siteIdObj, siteId] },
56831
+ createdAt: periodRange
56629
56832
  }
56630
56833
  },
56631
56834
  {
56632
- createdAt: {
56633
- $gte: new Date(range.previous.start),
56634
- $lte: new Date(range.previous.end)
56835
+ $unwind: "$checkPoints"
56836
+ },
56837
+ {
56838
+ $facet: {
56839
+ total: [{ $count: "count" }],
56840
+ completed: [
56841
+ { $match: { "checkPoints.status": "Completed" } },
56842
+ { $count: "count" }
56843
+ ],
56844
+ skipped: [
56845
+ { $match: { "checkPoints.status": "Skipped" } },
56846
+ { $count: "count" }
56847
+ ]
56635
56848
  }
56636
56849
  }
56637
- ]
56638
- });
56639
- return {
56640
- count: current,
56641
- percentage: calculatePercentage(current, previous)
56850
+ ]).toArray(),
56851
+ nfcPatrolLogCollection.aggregate([
56852
+ {
56853
+ $match: {
56854
+ site: { $in: [siteIdObj, siteId] },
56855
+ createdAt: { $gte: yesterday, $lte: yesterdayEnd }
56856
+ }
56857
+ },
56858
+ {
56859
+ $unwind: "$checkPoints"
56860
+ },
56861
+ {
56862
+ $facet: {
56863
+ total: [{ $count: "count" }],
56864
+ completed: [
56865
+ { $match: { "checkPoints.status": "Completed" } },
56866
+ { $count: "count" }
56867
+ ],
56868
+ skipped: [
56869
+ { $match: { "checkPoints.status": "Skipped" } },
56870
+ { $count: "count" }
56871
+ ]
56872
+ }
56873
+ }
56874
+ ]).toArray(),
56875
+ nfcPatrolLogCollection.aggregate([
56876
+ {
56877
+ $match: {
56878
+ site: { $in: [siteIdObj, siteId] },
56879
+ createdAt: { $gte: today, $lte: todayEnd }
56880
+ }
56881
+ },
56882
+ {
56883
+ $unwind: "$checkPoints"
56884
+ },
56885
+ {
56886
+ $facet: {
56887
+ total: [{ $count: "count" }],
56888
+ completed: [
56889
+ { $match: { "checkPoints.status": "Completed" } },
56890
+ { $count: "count" }
56891
+ ],
56892
+ skipped: [
56893
+ { $match: { "checkPoints.status": "Skipped" } },
56894
+ { $count: "count" }
56895
+ ]
56896
+ }
56897
+ }
56898
+ ]).toArray()
56899
+ ]);
56900
+ const wFacet = workOrderReport[0] ?? { total: [], inProgress: [] };
56901
+ const pFacet = patrolReport[0] ?? {
56902
+ total: [],
56903
+ completed: [],
56904
+ skipped: []
56642
56905
  };
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
56906
+ const totalCheckpoints = pFacet.total[0]?.count ?? 0;
56907
+ const completedCheckpoints = pFacet.completed[0]?.count ?? 0;
56908
+ const skippedCheckpoints = pFacet.skipped[0]?.count ?? 0;
56909
+ const complianceRate = totalCheckpoints > 0 ? Math.round(completedCheckpoints / totalCheckpoints * 100 * 100) / 100 : 100;
56910
+ const yPatrolFacet = yesterdayPatrolReport[0] ?? {
56911
+ total: [],
56912
+ completed: []
56913
+ };
56914
+ const yTotal = yPatrolFacet.total[0]?.count ?? 0;
56915
+ const yCompleted = yPatrolFacet.completed[0]?.count ?? 0;
56916
+ const yesterdayCompliance = yTotal > 0 ? yCompleted / yTotal * 100 : 0;
56917
+ const tPatrolFacet = todayPatrolReport[0] ?? {
56918
+ total: [],
56919
+ completed: []
56920
+ };
56921
+ const tTotal = tPatrolFacet.total[0]?.count ?? 0;
56922
+ const tCompleted = tPatrolFacet.completed[0]?.count ?? 0;
56923
+ const todayCompliance = tTotal > 0 ? tCompleted / tTotal * 100 : 0;
56924
+ const todayString = moment2.tz("Asia/Singapore").format("YYYY-MM-DD");
56925
+ const dayIndex = moment2.tz("Asia/Singapore").day();
56926
+ const routes = await db.collection("nfc-patrol-routes").find({
56927
+ site: { $in: [siteIdObj, siteId] },
56928
+ days: { $in: [dayIndex] },
56929
+ status: { $ne: "Inactive" }
56930
+ }).toArray();
56931
+ const expandedRoutes = [];
56932
+ for (const route of routes) {
56933
+ if (route.startTimes && Array.isArray(route.startTimes)) {
56934
+ for (const startTime of route.startTimes) {
56935
+ expandedRoutes.push({
56936
+ route,
56937
+ startTime,
56938
+ itemIndex: 0
56939
+ });
56940
+ }
56941
+ }
56942
+ }
56943
+ expandedRoutes.sort((a, b) => a.startTime.localeCompare(b.startTime));
56944
+ const limitedRoutes = expandedRoutes.slice(0, 4);
56945
+ limitedRoutes.forEach((item, idx) => {
56946
+ item.itemIndex = idx + 1;
56947
+ });
56948
+ const activePatrolItems = await Promise.all(
56949
+ limitedRoutes.map(async ({ route, startTime, itemIndex }) => {
56950
+ const log = await db.collection("nfc-patrol-logs").findOne({
56951
+ site: { $in: [siteIdObj, siteId] },
56952
+ date: todayString,
56953
+ "route._id": { $in: [route._id, route._id.toString()] },
56954
+ "route.startTime": startTime
56955
+ });
56956
+ let person = "Unassigned";
56957
+ if (log && log.createdBy) {
56958
+ const userDoc = await db.collection("users").findOne({
56959
+ _id: toObjectId16(log.createdBy)
56960
+ });
56961
+ if (userDoc && userDoc.name) {
56962
+ person = userDoc.name;
56963
+ }
56964
+ }
56965
+ let status = "pending";
56966
+ if (log) {
56967
+ status = "completed";
56968
+ } else {
56969
+ const routeTime = moment2.tz(
56970
+ `${todayString} ${startTime}`,
56971
+ "YYYY-MM-DD HH:mm",
56972
+ "Asia/Singapore"
56973
+ );
56974
+ const nowSg = moment2.tz("Asia/Singapore");
56975
+ const diffMinutes = nowSg.diff(routeTime, "minutes");
56976
+ if (diffMinutes >= 0) {
56977
+ if (diffMinutes <= 120) {
56978
+ status = "on paused";
56979
+ } else {
56980
+ status = "incomplete";
56981
+ }
56982
+ } else {
56983
+ status = "pending";
56984
+ }
56985
+ }
56986
+ return {
56987
+ id: `${route._id.toString()}_${startTime}`,
56988
+ title: route.name,
56989
+ subtitle: `ID${String(itemIndex).padStart(3, "0")}`,
56990
+ person,
56991
+ status,
56992
+ time: startTime
56993
+ };
56994
+ })
56683
56995
  );
56684
- const guests = await getMetric(guests_namespace_collection, siteId, guest);
56685
56996
  const data = {
56686
- feedbacks,
56687
- workOrders,
56688
- vehicles,
56689
- buildings,
56690
- visitors,
56691
- incidents,
56692
- guests
56997
+ openWorkOrder: {
56998
+ count: wFacet.total[0]?.count ?? 0,
56999
+ inProgress: wFacet.inProgress[0]?.count ?? 0,
57000
+ percentage: calculatePercentageChange(
57001
+ todayWorkOrderReport[0]?.count ?? 0,
57002
+ yesterdayWorkOrderReport[0]?.count ?? 0
57003
+ )
57004
+ },
57005
+ openIncidents: {
57006
+ count: incidentReport[0]?.count ?? 0,
57007
+ highSeverity: 0,
57008
+ percentage: calculatePercentageChange(
57009
+ todayIncidentReport[0]?.count ?? 0,
57010
+ yesterdayIncidentReport[0]?.count ?? 0
57011
+ )
57012
+ },
57013
+ visitors: {
57014
+ count: visitorReport[0]?.count ?? 0,
57015
+ currentlyOnSite: currentlyOnSiteCount,
57016
+ percentage: calculatePercentageChange(
57017
+ todayVisitorReport[0]?.count ?? 0,
57018
+ yesterdayVisitorReport[0]?.count ?? 0
57019
+ )
57020
+ },
57021
+ patrolCompliance: {
57022
+ count: complianceRate,
57023
+ missedCheckpoints: skippedCheckpoints,
57024
+ missed: skippedCheckpoints,
57025
+ percentage: calculatePercentageChange(
57026
+ todayCompliance,
57027
+ yesterdayCompliance
57028
+ )
57029
+ },
57030
+ activePatrolItems
56693
57031
  };
56694
57032
  return data;
56695
57033
  }
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
57034
+ async function getPropertyManagementDashboard(siteId, period = "today" /* TODAY */, type, facility) {
57035
+ const siteIdObj = toObjectId16(siteId);
57036
+ const startOfToday = moment2.tz("Asia/Singapore").startOf("day").toDate();
57037
+ const endOfToday = moment2.tz("Asia/Singapore").endOf("day").toDate();
57038
+ const upcomingEvents = await db.collection(events_namespace_collection).find({
57039
+ site: { $in: [siteIdObj, siteId] },
57040
+ status: { $nin: ["deleted", "Deleted"] },
57041
+ $or: [
57042
+ { dateTime: { $gte: startOfToday } },
57043
+ { dateTime: { $gte: startOfToday.toISOString() } }
57044
+ ]
57045
+ }).sort({ dateTime: 1 }).limit(4).toArray();
57046
+ const todayReminders = await db.collection(events_namespace_collection).find({
57047
+ site: { $in: [siteIdObj, siteId] },
57048
+ status: { $nin: ["deleted", "Deleted"] },
57049
+ $or: [
57050
+ { dateTime: { $gte: startOfToday, $lte: endOfToday } },
57051
+ {
57052
+ dateTime: {
57053
+ $gte: startOfToday.toISOString(),
57054
+ $lte: endOfToday.toISOString()
57055
+ }
57056
+ }
57057
+ ]
57058
+ }).sort({ dateTime: 1 }).limit(4).toArray();
57059
+ const [pendingIncidentDocs, pendingFacilityBookingDocs] = await Promise.all(
57060
+ [
57061
+ db.collection(incidents_namespace_collection).find({
57062
+ site: { $in: [siteIdObj, siteId] },
57063
+ status: { $in: ["pending", "Pending"] }
57064
+ }).sort({ createdAt: -1 }).toArray(),
57065
+ db.collection(facility_bookings_namespace_collection2).find({
57066
+ site: { $in: [siteIdObj, siteId] },
57067
+ status: { $in: ["Pending", "pending", "For Review", "for review"] }
57068
+ }).sort({ createdAt: -1 }).toArray()
57069
+ ]
56743
57070
  );
56744
- const bulletinBoards = await getMetric(
56745
- bulletin_boards_namespace_collection,
56746
- siteId,
56747
- bulletinBoard
57071
+ const pendingIncidentCount = pendingIncidentDocs.length;
57072
+ const pendingFacilityBookingCount = pendingFacilityBookingDocs.length;
57073
+ const todayAttentions = [];
57074
+ if (pendingIncidentCount > 0) {
57075
+ todayAttentions.push({
57076
+ id: "incidents-pending",
57077
+ title: `${pendingIncidentCount} incident${pendingIncidentCount === 1 ? "" : "s"} pending acknowledge`,
57078
+ createdAt: pendingIncidentDocs[0].updatedAt || pendingIncidentDocs[0].createdAt || /* @__PURE__ */ new Date()
57079
+ });
57080
+ }
57081
+ if (pendingFacilityBookingCount > 0) {
57082
+ todayAttentions.push({
57083
+ id: "facility-booking-pending",
57084
+ title: `${pendingFacilityBookingCount} facility booking${pendingFacilityBookingCount === 1 ? "" : "s"} need approval`,
57085
+ createdAt: pendingFacilityBookingDocs[0].createdAt || /* @__PURE__ */ new Date()
57086
+ });
57087
+ }
57088
+ todayAttentions.sort(
57089
+ (a, b) => new Date(b.createdAt).getTime() - new Date(a.createdAt).getTime()
56748
57090
  );
56749
- const events = await getMetric(events_namespace_collection, siteId, event);
56750
- const facilityBookings = await getMetric(
56751
- facility_bookings_namespace_collection,
56752
- siteId,
56753
- facilityBooking
57091
+ const visitorMatchObj = {};
57092
+ if (type) {
57093
+ visitorMatchObj.type = type;
57094
+ }
57095
+ const facilityMatchObj = {};
57096
+ if (facility) {
57097
+ try {
57098
+ facilityMatchObj.facility = { $in: [facility, new ObjectId121(facility)] };
57099
+ } catch (e) {
57100
+ facilityMatchObj.facility = facility;
57101
+ }
57102
+ }
57103
+ const today = /* @__PURE__ */ new Date();
57104
+ today.setHours(0, 0, 0, 0);
57105
+ const yesterday = /* @__PURE__ */ new Date();
57106
+ yesterday.setDate(today.getDate() - 1);
57107
+ yesterday.setHours(0, 0, 0, 0);
57108
+ const yesterdayEnd = new Date(yesterday);
57109
+ yesterdayEnd.setHours(23, 59, 59, 999);
57110
+ const todayEnd = formatEndDate(/* @__PURE__ */ new Date());
57111
+ const periodRange = getDateRange(period);
57112
+ const incidentCollection = db.collection(incidents_namespace_collection);
57113
+ const visitorCollection = db.collection(visitors_namespace_collection);
57114
+ const facilityCollection = db.collection(
57115
+ facility_bookings_namespace_collection2
56754
57116
  );
57117
+ const [
57118
+ workOrderReport,
57119
+ yesterdayWorkOrderReport,
57120
+ todayWorkOrderReport,
57121
+ incidentReport,
57122
+ yesterdayIncidentReport,
57123
+ todayIncidentReport,
57124
+ visitorReport,
57125
+ yesterdayVisitorReport,
57126
+ todayVisitorReport,
57127
+ currentlyOnSiteCount,
57128
+ facilityReport,
57129
+ yesterdayFacilityReport,
57130
+ todayFacilityReport
57131
+ ] = await Promise.all([
57132
+ workOrderCollection.aggregate([
57133
+ {
57134
+ $match: {
57135
+ site: { $in: [siteIdObj, siteId] },
57136
+ createdAt: periodRange,
57137
+ status: { $nin: ["completed"] }
57138
+ }
57139
+ },
57140
+ {
57141
+ $facet: {
57142
+ total: [{ $count: "count" }],
57143
+ inProgress: [
57144
+ { $match: { status: "in-progress" } },
57145
+ { $count: "count" }
57146
+ ]
57147
+ }
57148
+ }
57149
+ ]).toArray(),
57150
+ workOrderCollection.aggregate([
57151
+ {
57152
+ $match: {
57153
+ site: { $in: [siteIdObj, siteId] },
57154
+ createdAt: { $gte: yesterday, $lte: yesterdayEnd },
57155
+ status: { $nin: ["completed"] }
57156
+ }
57157
+ },
57158
+ { $count: "count" }
57159
+ ]).toArray(),
57160
+ workOrderCollection.aggregate([
57161
+ {
57162
+ $match: {
57163
+ site: { $in: [siteIdObj, siteId] },
57164
+ createdAt: { $gte: today, $lte: todayEnd },
57165
+ status: { $nin: ["completed"] }
57166
+ }
57167
+ },
57168
+ { $count: "count" }
57169
+ ]).toArray(),
57170
+ incidentCollection.aggregate([
57171
+ {
57172
+ $match: {
57173
+ site: { $in: [siteIdObj, siteId] },
57174
+ status: { $in: ["pending", "Pending"] },
57175
+ createdAt: periodRange
57176
+ }
57177
+ },
57178
+ { $count: "count" }
57179
+ ]).toArray(),
57180
+ incidentCollection.aggregate([
57181
+ {
57182
+ $match: {
57183
+ site: { $in: [siteIdObj, siteId] },
57184
+ status: { $in: ["pending", "Pending"] },
57185
+ createdAt: { $gte: yesterday, $lte: yesterdayEnd }
57186
+ }
57187
+ },
57188
+ { $count: "count" }
57189
+ ]).toArray(),
57190
+ incidentCollection.aggregate([
57191
+ {
57192
+ $match: {
57193
+ site: { $in: [siteIdObj, siteId] },
57194
+ status: { $in: ["pending", "Pending"] },
57195
+ createdAt: { $gte: today, $lte: todayEnd }
57196
+ }
57197
+ },
57198
+ { $count: "count" }
57199
+ ]).toArray(),
57200
+ visitorCollection.aggregate([
57201
+ {
57202
+ $match: {
57203
+ site: { $in: [siteIdObj, siteId] },
57204
+ ...visitorMatchObj,
57205
+ createdAt: periodRange,
57206
+ status: { $ne: "deleted" }
57207
+ }
57208
+ },
57209
+ { $count: "count" }
57210
+ ]).toArray(),
57211
+ visitorCollection.aggregate([
57212
+ {
57213
+ $match: {
57214
+ site: { $in: [siteIdObj, siteId] },
57215
+ ...visitorMatchObj,
57216
+ createdAt: { $gte: yesterday, $lte: yesterdayEnd },
57217
+ status: { $ne: "deleted" }
57218
+ }
57219
+ },
57220
+ { $count: "count" }
57221
+ ]).toArray(),
57222
+ visitorCollection.aggregate([
57223
+ {
57224
+ $match: {
57225
+ site: { $in: [siteIdObj, siteId] },
57226
+ ...visitorMatchObj,
57227
+ createdAt: { $gte: today, $lte: todayEnd },
57228
+ status: { $ne: "deleted" }
57229
+ }
57230
+ },
57231
+ { $count: "count" }
57232
+ ]).toArray(),
57233
+ visitorCollection.countDocuments({
57234
+ site: { $in: [siteIdObj, siteId] },
57235
+ ...visitorMatchObj,
57236
+ checkIn: { $ne: null },
57237
+ checkOut: null,
57238
+ status: { $ne: "deleted" }
57239
+ }),
57240
+ facilityCollection.aggregate([
57241
+ {
57242
+ $match: {
57243
+ site: { $in: [siteIdObj, siteId] },
57244
+ ...facilityMatchObj,
57245
+ $or: [
57246
+ { createdAt: periodRange },
57247
+ {
57248
+ createdAt: {
57249
+ $gte: periodRange.$gte.toISOString(),
57250
+ $lte: periodRange.$lte.toISOString()
57251
+ }
57252
+ }
57253
+ ],
57254
+ status: { $nin: ["deleted", "Deleted"] }
57255
+ }
57256
+ },
57257
+ {
57258
+ $facet: {
57259
+ total: [{ $count: "count" }],
57260
+ ongoing: [
57261
+ {
57262
+ $match: {
57263
+ status: {
57264
+ $in: ["Approved", "Ongoing"]
57265
+ }
57266
+ }
57267
+ },
57268
+ { $count: "count" }
57269
+ ],
57270
+ waitingApproval: [
57271
+ {
57272
+ $match: {
57273
+ status: {
57274
+ $in: ["Pending", "pending", "For Review", "for review"]
57275
+ }
57276
+ }
57277
+ },
57278
+ { $count: "count" }
57279
+ ]
57280
+ }
57281
+ }
57282
+ ]).toArray(),
57283
+ facilityCollection.aggregate([
57284
+ {
57285
+ $match: {
57286
+ site: { $in: [siteIdObj, siteId] },
57287
+ ...facilityMatchObj,
57288
+ $or: [
57289
+ { createdAt: { $gte: yesterday, $lte: yesterdayEnd } },
57290
+ {
57291
+ createdAt: {
57292
+ $gte: yesterday.toISOString(),
57293
+ $lte: yesterdayEnd.toISOString()
57294
+ }
57295
+ }
57296
+ ],
57297
+ status: { $nin: ["deleted", "Deleted"] }
57298
+ }
57299
+ },
57300
+ { $count: "count" }
57301
+ ]).toArray(),
57302
+ facilityCollection.aggregate([
57303
+ {
57304
+ $match: {
57305
+ site: { $in: [siteIdObj, siteId] },
57306
+ ...facilityMatchObj,
57307
+ $or: [
57308
+ { createdAt: { $gte: today, $lte: todayEnd } },
57309
+ {
57310
+ createdAt: {
57311
+ $gte: today.toISOString(),
57312
+ $lte: todayEnd.toISOString()
57313
+ }
57314
+ }
57315
+ ],
57316
+ status: { $nin: ["deleted", "Deleted"] }
57317
+ }
57318
+ },
57319
+ { $count: "count" }
57320
+ ]).toArray()
57321
+ ]);
57322
+ const wFacet = workOrderReport[0] ?? { total: [], inProgress: [] };
57323
+ const fFacet = facilityReport[0] ?? {
57324
+ total: [],
57325
+ ongoing: [],
57326
+ waitingApproval: []
57327
+ };
56755
57328
  const data = {
56756
- feedbacks,
56757
- workOrders,
56758
- vehicles,
56759
- buildings,
56760
- visitors,
56761
- incidents,
56762
- sitePeople: _sitePeople,
56763
- bulletinBoards,
56764
- events,
56765
- facilityBookings
57329
+ openWorkOrder: {
57330
+ count: wFacet.total[0]?.count ?? 0,
57331
+ inProgress: wFacet.inProgress[0]?.count ?? 0,
57332
+ percentage: calculatePercentageChange(
57333
+ todayWorkOrderReport[0]?.count ?? 0,
57334
+ yesterdayWorkOrderReport[0]?.count ?? 0
57335
+ )
57336
+ },
57337
+ openIncidents: {
57338
+ count: incidentReport[0]?.count ?? 0,
57339
+ highSeverity: 0,
57340
+ percentage: calculatePercentageChange(
57341
+ todayIncidentReport[0]?.count ?? 0,
57342
+ yesterdayIncidentReport[0]?.count ?? 0
57343
+ )
57344
+ },
57345
+ visitors: {
57346
+ count: visitorReport[0]?.count ?? 0,
57347
+ currentlyOnSite: currentlyOnSiteCount,
57348
+ percentage: calculatePercentageChange(
57349
+ todayVisitorReport[0]?.count ?? 0,
57350
+ yesterdayVisitorReport[0]?.count ?? 0
57351
+ )
57352
+ },
57353
+ facilityBooking: {
57354
+ count: fFacet.total[0]?.count ?? 0,
57355
+ ongoing: fFacet.ongoing[0]?.count ?? 0,
57356
+ waitingApproval: fFacet.waitingApproval[0]?.count ?? 0,
57357
+ percentage: calculatePercentageChange(
57358
+ todayFacilityReport[0]?.count ?? 0,
57359
+ yesterdayFacilityReport[0]?.count ?? 0
57360
+ )
57361
+ },
57362
+ upcomingEvents,
57363
+ todayReminders,
57364
+ todayAttentions
56766
57365
  };
56767
57366
  return data;
56768
57367
  }
@@ -56792,61 +57391,13 @@ function useNewDashboardRepo() {
56792
57391
  async function getServiceDashboard({
56793
57392
  site,
56794
57393
  serviceType,
56795
- period = "today" /* TODAY */,
56796
- type,
56797
- facility
57394
+ period = "today" /* TODAY */
56798
57395
  }) {
56799
57396
  try {
56800
57397
  site = new ObjectId121(site);
56801
57398
  } catch (error) {
56802
57399
  throw new BadRequestError182("Invalid site ID format.");
56803
57400
  }
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
57401
  const today = /* @__PURE__ */ new Date();
56851
57402
  today.setHours(0, 0, 0, 0);
56852
57403
  const yesterday = /* @__PURE__ */ new Date();
@@ -56857,530 +57408,6 @@ function useNewDashboardRepo() {
56857
57408
  const todayEnd = formatEndDate(/* @__PURE__ */ new Date());
56858
57409
  const periodRange = getDateRange(period);
56859
57410
  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
57411
  const workOrderService = workOrderServiceMap[serviceType] ?? serviceType;
57385
57412
  const [
57386
57413
  workOrderReport,
@@ -57887,13 +57914,8 @@ function useNewDashboardController() {
57887
57914
  try {
57888
57915
  const schema2 = Joi112.object({
57889
57916
  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
57917
+ period: periodField,
57918
+ type: Joi112.string().optional().allow("", null)
57897
57919
  });
57898
57920
  const { error, value } = schema2.validate({
57899
57921
  site: req.params.site,
@@ -57905,25 +57927,11 @@ function useNewDashboardController() {
57905
57927
  next(new BadRequestError183(messages));
57906
57928
  return;
57907
57929
  }
57908
- const {
57909
- site,
57910
- feedbackPeriod,
57911
- workOrderPeriod,
57912
- vehiclePeriod,
57913
- buildingPeriod,
57914
- visitorPeriod,
57915
- incidentPeriod,
57916
- guestPeriod
57917
- } = value;
57930
+ const { site, period, type } = value;
57918
57931
  const data = await _getSecurityDashboard({
57919
57932
  siteId: site,
57920
- feedback: feedbackPeriod,
57921
- workOrder: workOrderPeriod,
57922
- vehicle: vehiclePeriod,
57923
- building: buildingPeriod,
57924
- visitor: visitorPeriod,
57925
- incident: incidentPeriod,
57926
- guest: guestPeriod
57933
+ period,
57934
+ type
57927
57935
  });
57928
57936
  res.status(200).json(data);
57929
57937
  return;
@@ -57937,16 +57945,9 @@ function useNewDashboardController() {
57937
57945
  try {
57938
57946
  const schema2 = Joi112.object({
57939
57947
  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
57948
+ period: periodField,
57949
+ type: Joi112.string().optional().allow("", null),
57950
+ facility: Joi112.string().hex().optional().allow("", null)
57950
57951
  });
57951
57952
  const { error, value } = schema2.validate({
57952
57953
  site: req.params.site,
@@ -57958,32 +57959,13 @@ function useNewDashboardController() {
57958
57959
  next(new BadRequestError183(messages));
57959
57960
  return;
57960
57961
  }
57961
- const {
57962
+ const { site, period, type, facility } = value;
57963
+ const data = await _getPropertyManagementDashboard(
57962
57964
  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
- });
57965
+ period,
57966
+ type,
57967
+ facility
57968
+ );
57987
57969
  res.status(200).json(data);
57988
57970
  return;
57989
57971
  } catch (error) {
@@ -57997,9 +57979,7 @@ function useNewDashboardController() {
57997
57979
  const validation = Joi112.object({
57998
57980
  site: Joi112.string().hex().required(),
57999
57981
  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)
57982
+ period: Joi112.string().valid(...Object.values(Period)).default("today" /* TODAY */)
58003
57983
  });
58004
57984
  const { error } = validation.validate(query);
58005
57985
  if (error) {
@@ -58010,15 +57990,11 @@ function useNewDashboardController() {
58010
57990
  const site = req.params.site ?? "";
58011
57991
  const serviceType = req.params.serviceType;
58012
57992
  const period = req.query.period;
58013
- const type = req.query.type;
58014
- const facility = req.query.facility;
58015
57993
  try {
58016
57994
  const data = await _getServiceDashboard({
58017
57995
  site,
58018
57996
  period,
58019
- serviceType,
58020
- type,
58021
- facility
57997
+ serviceType
58022
57998
  });
58023
57999
  res.json(data);
58024
58000
  return;
@@ -58043,7 +58019,11 @@ function useNewDashboardController() {
58043
58019
  }
58044
58020
  const { site, serviceType, period } = value;
58045
58021
  try {
58046
- const data = await _getServiceWeeklyActivity({ site, serviceType, period });
58022
+ const data = await _getServiceWeeklyActivity({
58023
+ site,
58024
+ serviceType,
58025
+ period
58026
+ });
58047
58027
  res.json(data);
58048
58028
  return;
58049
58029
  } catch (error2) {
@@ -66215,7 +66195,11 @@ import Joi143 from "joi";
66215
66195
  import { BadRequestError as BadRequestError221, InternalServerError as InternalServerError81, useAtlas as useAtlas126 } from "@7365admin1/node-server-utils";
66216
66196
 
66217
66197
  // src/repositories/channel-preloved.repo.ts
66218
- import { InternalServerError as InternalServerError80, useAtlas as useAtlas125 } from "@7365admin1/node-server-utils";
66198
+ import {
66199
+ InternalServerError as InternalServerError80,
66200
+ paginate as paginate63,
66201
+ useAtlas as useAtlas125
66202
+ } from "@7365admin1/node-server-utils";
66219
66203
  import { ObjectId as ObjectId148 } from "mongodb";
66220
66204
 
66221
66205
  // src/models/channel-preloved.model.ts
@@ -66263,6 +66247,7 @@ function useChannelPrelovedRepo() {
66263
66247
  if (!db)
66264
66248
  throw new InternalServerError80("Unable to connect to server.");
66265
66249
  const CHANNEL_COLLECTION = "channel-preloved";
66250
+ const CHAT_COLLECTION = "chat-preloved";
66266
66251
  const collection = db.collection(CHANNEL_COLLECTION);
66267
66252
  async function add(value, session) {
66268
66253
  try {
@@ -66281,7 +66266,85 @@ function useChannelPrelovedRepo() {
66281
66266
  };
66282
66267
  return collection.findOne(query, { session });
66283
66268
  }
66284
- return { add, getByParticipants };
66269
+ async function getChannelMessages(channelId, page = 1, limit = 10, isLoadMore = false, lastMessageId = null) {
66270
+ const chatCollection = db.collection(CHAT_COLLECTION);
66271
+ const normalizedPage = page > 0 ? page - 1 : 0;
66272
+ const normalizedLimit = limit || 10;
66273
+ const matchCriteria = {
66274
+ channelId: new ObjectId148(channelId),
66275
+ deletedAt: null
66276
+ };
66277
+ if (isLoadMore && lastMessageId) {
66278
+ matchCriteria._id = { $lt: new ObjectId148(lastMessageId) };
66279
+ }
66280
+ try {
66281
+ const result = await chatCollection.aggregate([
66282
+ { $match: matchCriteria },
66283
+ {
66284
+ $lookup: {
66285
+ from: "users",
66286
+ localField: "senderId",
66287
+ foreignField: "_id",
66288
+ pipeline: [
66289
+ {
66290
+ $project: {
66291
+ name: 1,
66292
+ profile: 1,
66293
+ type: 1
66294
+ }
66295
+ }
66296
+ ],
66297
+ as: "senderId"
66298
+ }
66299
+ },
66300
+ { $unwind: { path: "$senderId", preserveNullAndEmptyArrays: true } },
66301
+ {
66302
+ $lookup: {
66303
+ from: "bid-preloved",
66304
+ localField: "bidId",
66305
+ foreignField: "_id",
66306
+ pipeline: [
66307
+ { $project: { price: 1, message: 1, status: 1, type: 1 } }
66308
+ ],
66309
+ as: "bidId"
66310
+ }
66311
+ },
66312
+ { $unwind: { path: "$bidId", preserveNullAndEmptyArrays: true } },
66313
+ {
66314
+ $lookup: {
66315
+ from: "post-preloved",
66316
+ localField: "postId",
66317
+ foreignField: "_id",
66318
+ pipeline: [{ $project: { title: 1, status: 1, reserverId: 1 } }],
66319
+ as: "postDetails"
66320
+ }
66321
+ },
66322
+ {
66323
+ $unwind: {
66324
+ path: "$postDetails",
66325
+ preserveNullAndEmptyArrays: true
66326
+ }
66327
+ },
66328
+ { $sort: { createdAt: -1 } },
66329
+ {
66330
+ $facet: {
66331
+ totalCount: [{ $count: "count" }],
66332
+ items: [
66333
+ { $skip: normalizedPage * normalizedLimit },
66334
+ { $limit: normalizedLimit }
66335
+ ]
66336
+ }
66337
+ }
66338
+ ]).toArray();
66339
+ const totalCount = result[0].totalCount[0]?.count ?? 0;
66340
+ const items = result[0].items;
66341
+ items.reverse();
66342
+ return paginate63(items, normalizedPage, normalizedLimit, totalCount);
66343
+ } catch (error) {
66344
+ throw error;
66345
+ }
66346
+ }
66347
+ return { add, getByParticipants, getChannelMessages };
66285
66348
  }
66286
66349
 
66287
66350
  // src/services/chat-preloved.service.ts
@@ -66397,8 +66460,9 @@ function useChatPrelovedController() {
66397
66460
 
66398
66461
  // src/controllers/channel-preloved.controller.ts
66399
66462
  import { BadRequestError as BadRequestError223, logger as logger193 } from "@7365admin1/node-server-utils";
66463
+ import Joi144 from "joi";
66400
66464
  function useChannelPrelovedController() {
66401
- const { add: _add } = useChannelPrelovedRepo();
66465
+ const { add: _add, getChannelMessages: _getChannelMessages } = useChannelPrelovedRepo();
66402
66466
  async function add(req, res, next) {
66403
66467
  const { error, value } = schemaChannelPreloved.validate(req.body, {
66404
66468
  abortEarly: false
@@ -66417,11 +66481,51 @@ function useChannelPrelovedController() {
66417
66481
  next(error2);
66418
66482
  }
66419
66483
  }
66420
- return { add };
66484
+ async function getChannelMessages(req, res, next) {
66485
+ const paramsSchema = Joi144.object({
66486
+ id: Joi144.string().hex().length(24).required()
66487
+ });
66488
+ const querySchema = Joi144.object({
66489
+ page: Joi144.number().integer().min(1).default(1),
66490
+ limit: Joi144.number().integer().min(1).max(100).default(10),
66491
+ isLoadMore: Joi144.boolean().default(false),
66492
+ lastMessageId: Joi144.string().hex().length(24).optional().allow("", null)
66493
+ });
66494
+ const { error: paramError, value: params } = paramsSchema.validate(
66495
+ req.params
66496
+ );
66497
+ if (paramError) {
66498
+ logger193.log({ level: "error", message: paramError.message });
66499
+ next(new BadRequestError223(paramError.message));
66500
+ return;
66501
+ }
66502
+ const { error: queryError, value: query } = querySchema.validate(
66503
+ req.query
66504
+ );
66505
+ if (queryError) {
66506
+ logger193.log({ level: "error", message: queryError.message });
66507
+ next(new BadRequestError223(queryError.message));
66508
+ return;
66509
+ }
66510
+ try {
66511
+ const data = await _getChannelMessages(
66512
+ params.id,
66513
+ query.page,
66514
+ query.limit,
66515
+ query.isLoadMore,
66516
+ query.lastMessageId || null
66517
+ );
66518
+ res.status(200).json(data);
66519
+ } catch (error) {
66520
+ logger193.log({ level: "error", message: error.message });
66521
+ next(error);
66522
+ }
66523
+ }
66524
+ return { add, getChannelMessages };
66421
66525
  }
66422
66526
 
66423
66527
  // src/models/online-forms-v2.model.ts
66424
- import Joi144 from "joi";
66528
+ import Joi145 from "joi";
66425
66529
  import { ObjectId as ObjectId149 } from "mongodb";
66426
66530
  var FormEntryStatus = /* @__PURE__ */ ((FormEntryStatus2) => {
66427
66531
  FormEntryStatus2["ACTIVE"] = "active";
@@ -66429,49 +66533,49 @@ var FormEntryStatus = /* @__PURE__ */ ((FormEntryStatus2) => {
66429
66533
  FormEntryStatus2["DELETED"] = "deleted";
66430
66534
  return FormEntryStatus2;
66431
66535
  })(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)
66536
+ var schemaFormEntry = Joi145.object({
66537
+ _id: Joi145.string().hex().optional().allow("", null),
66538
+ formType: Joi145.string().required(),
66539
+ block: Joi145.string().optional().allow(null, ""),
66540
+ level: Joi145.string().optional().allow(null, ""),
66541
+ unit: Joi145.string().optional().allow(null, ""),
66542
+ name: Joi145.string().optional().allow(null, ""),
66543
+ phoneNumber: Joi145.string().optional().allow(null, ""),
66544
+ createdBy: Joi145.string().required(),
66545
+ fields: Joi145.object().pattern(
66546
+ Joi145.string(),
66547
+ Joi145.alternatives().try(
66548
+ Joi145.string(),
66549
+ Joi145.number(),
66550
+ Joi145.boolean(),
66551
+ Joi145.valid(null)
66448
66552
  )
66449
66553
  ).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)
66554
+ status: Joi145.string().optional().allow("", null),
66555
+ org: Joi145.string().hex().optional().allow("", null),
66556
+ site: Joi145.string().hex().optional().allow("", null),
66557
+ createdAt: Joi145.date().optional().allow("", null),
66558
+ updatedAt: Joi145.date().optional().allow("", null),
66559
+ deletedAt: Joi145.date().optional().allow("", null)
66456
66560
  });
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)
66561
+ var schemaUpdateFormEntry = Joi145.object({
66562
+ _id: Joi145.string().hex().required(),
66563
+ formType: Joi145.string().optional().allow("", null),
66564
+ block: Joi145.string().optional().allow(null, ""),
66565
+ level: Joi145.string().optional().allow(null, ""),
66566
+ unit: Joi145.string().optional().allow(null, ""),
66567
+ fields: Joi145.object().pattern(
66568
+ Joi145.string(),
66569
+ Joi145.alternatives().try(
66570
+ Joi145.string(),
66571
+ Joi145.number(),
66572
+ Joi145.boolean(),
66573
+ Joi145.valid(null)
66470
66574
  )
66471
66575
  ).optional(),
66472
- status: Joi144.string().optional().allow("", null),
66473
- updatedAt: Joi144.date().optional().allow("", null),
66474
- deletedAt: Joi144.date().optional().allow("", null)
66576
+ status: Joi145.string().optional().allow("", null),
66577
+ updatedAt: Joi145.date().optional().allow("", null),
66578
+ deletedAt: Joi145.date().optional().allow("", null)
66475
66579
  });
66476
66580
  function MFormEntry(value) {
66477
66581
  const { error } = schemaFormEntry.validate(value);
@@ -66516,34 +66620,34 @@ function MFormEntry(value) {
66516
66620
  deletedAt: value.deletedAt ?? null
66517
66621
  };
66518
66622
  }
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)
66623
+ var residentFormEntry = Joi145.object({
66624
+ _id: Joi145.string().hex().optional().allow("", null),
66625
+ typeOfForm: Joi145.string().optional().allow("", null),
66626
+ unitNumber: Joi145.string().optional().allow(null, ""),
66627
+ fields: Joi145.object().pattern(
66628
+ Joi145.string(),
66629
+ Joi145.alternatives().try(
66630
+ Joi145.string(),
66631
+ Joi145.number(),
66632
+ Joi145.boolean(),
66633
+ Joi145.valid(null)
66530
66634
  )
66531
66635
  ).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)
66636
+ status: Joi145.string().optional().allow("", null),
66637
+ org: Joi145.string().hex().optional().allow("", null),
66638
+ site: Joi145.string().hex().optional().allow("", null),
66639
+ userId: Joi145.string().hex().optional().allow("", null),
66640
+ createdAt: Joi145.date().optional().allow("", null),
66641
+ updatedAt: Joi145.date().optional().allow("", null),
66642
+ deletedAt: Joi145.date().optional().allow("", null),
66643
+ remarks: Joi145.string().optional().allow("", null),
66644
+ managementValues: Joi145.object().pattern(
66645
+ Joi145.string(),
66646
+ Joi145.alternatives().try(
66647
+ Joi145.string(),
66648
+ Joi145.number(),
66649
+ Joi145.boolean(),
66650
+ Joi145.valid(null)
66547
66651
  )
66548
66652
  ).optional().allow(null, "")
66549
66653
  });
@@ -66555,7 +66659,7 @@ import {
66555
66659
  logger as logger194,
66556
66660
  makeCacheKey as makeCacheKey65,
66557
66661
  NotFoundError as NotFoundError61,
66558
- paginate as paginate63,
66662
+ paginate as paginate64,
66559
66663
  useAtlas as useAtlas127,
66560
66664
  useCache as useCache69
66561
66665
  } from "@7365admin1/node-server-utils";
@@ -66653,7 +66757,7 @@ function useFormEntryRepo() {
66653
66757
  { $limit: limit }
66654
66758
  ]).toArray();
66655
66759
  const length = await collection.countDocuments(query);
66656
- const data = paginate63(items, page, limit, length);
66760
+ const data = paginate64(items, page, limit, length);
66657
66761
  setCache(cacheKey, data, 15 * 60).then(() => {
66658
66762
  logger194.info(`Cache set for key: ${cacheKey}`);
66659
66763
  }).catch((err) => {
@@ -66813,7 +66917,7 @@ function useFormEntryRepo() {
66813
66917
 
66814
66918
  // src/controllers/online-forms-v2.controller.ts
66815
66919
  import { BadRequestError as BadRequestError225, logger as logger195 } from "@7365admin1/node-server-utils";
66816
- import Joi145 from "joi";
66920
+ import Joi146 from "joi";
66817
66921
  import ExcelJS3 from "exceljs";
66818
66922
  import fs6 from "fs";
66819
66923
  function useFormEntryController() {
@@ -66889,13 +66993,13 @@ function useFormEntryController() {
66889
66993
  }
66890
66994
  async function getAll(req, res, next) {
66891
66995
  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)
66996
+ const schema2 = Joi146.object({
66997
+ search: Joi146.string().optional().allow("", null),
66998
+ page: Joi146.number().integer().min(1).allow("", null).default(1),
66999
+ limit: Joi146.number().integer().min(1).max(100).allow("", null).default(10),
67000
+ status: Joi146.string().optional().allow(null, ""),
67001
+ org: Joi146.string().hex().optional().allow("", null),
67002
+ site: Joi146.string().hex().optional().allow("", null)
66899
67003
  });
66900
67004
  const { error, value } = schema2.validate(req.query);
66901
67005
  if (error) {
@@ -66916,8 +67020,8 @@ function useFormEntryController() {
66916
67020
  }
66917
67021
  async function getFormEntryById(req, res, next) {
66918
67022
  try {
66919
- const schema2 = Joi145.object({
66920
- _id: Joi145.string().hex().length(24).required()
67023
+ const schema2 = Joi146.object({
67024
+ _id: Joi146.string().hex().length(24).required()
66921
67025
  });
66922
67026
  const { error, value } = schema2.validate({ _id: req.params.id });
66923
67027
  if (error) {
@@ -66960,7 +67064,7 @@ function useFormEntryController() {
66960
67064
  }
66961
67065
  async function deleteFormEntryById(req, res, next) {
66962
67066
  try {
66963
- const validation = Joi145.string().hex().required();
67067
+ const validation = Joi146.string().hex().required();
66964
67068
  const _id = req.params.id;
66965
67069
  const { error } = validation.validate(_id);
66966
67070
  if (error) {
@@ -67027,10 +67131,10 @@ function useFormEntryController() {
67027
67131
  async function residentForm(req, res, next) {
67028
67132
  try {
67029
67133
  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()
67134
+ const residentFormPayload = Joi146.object({
67135
+ org: Joi146.string().hex().required(),
67136
+ site: Joi146.string().hex().required(),
67137
+ userId: Joi146.string().hex().required()
67034
67138
  });
67035
67139
  const { error } = residentFormPayload.validate({ site, userId, org }, { abortEarly: true });
67036
67140
  if (error) {
@@ -67099,7 +67203,7 @@ function useBuildingLevelService() {
67099
67203
 
67100
67204
  // src/controllers/building-level.controller.ts
67101
67205
  import { BadRequestError as BadRequestError226, logger as logger196 } from "@7365admin1/node-server-utils";
67102
- import Joi146 from "joi";
67206
+ import Joi147 from "joi";
67103
67207
  function useBuildingLevelController() {
67104
67208
  const { add: _add, updateLevelById: _updateLevelById } = useBuildingLevelService();
67105
67209
  const {
@@ -67128,12 +67232,12 @@ function useBuildingLevelController() {
67128
67232
  }
67129
67233
  async function getAll(req, res, next) {
67130
67234
  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 */)
67235
+ const validation = Joi147.object({
67236
+ page: Joi147.number().min(1).optional().default(1),
67237
+ limit: Joi147.number().min(1).optional().default(20),
67238
+ search: Joi147.string().optional().allow("", null),
67239
+ site: Joi147.string().hex().length(24).optional().allow("", null),
67240
+ status: Joi147.string().valid(...Object.values(BuildingLevelStatus)).default("active" /* ACTIVE */)
67137
67241
  });
67138
67242
  const { error, value } = validation.validate(req.query, {
67139
67243
  abortEarly: false
@@ -67160,8 +67264,8 @@ function useBuildingLevelController() {
67160
67264
  }
67161
67265
  async function getById(req, res, next) {
67162
67266
  try {
67163
- const schema2 = Joi146.object({
67164
- id: Joi146.string().hex().length(24).required()
67267
+ const schema2 = Joi147.object({
67268
+ id: Joi147.string().hex().length(24).required()
67165
67269
  });
67166
67270
  const { error, value } = schema2.validate({ id: req.params.id });
67167
67271
  if (error) {
@@ -67199,8 +67303,8 @@ function useBuildingLevelController() {
67199
67303
  }
67200
67304
  async function deleteById(req, res, next) {
67201
67305
  try {
67202
- const schema2 = Joi146.object({
67203
- id: Joi146.string().hex().required()
67306
+ const schema2 = Joi147.object({
67307
+ id: Joi147.string().hex().required()
67204
67308
  });
67205
67309
  const { error, value } = schema2.validate({ id: req.params.id });
67206
67310
  if (error) {
@@ -67219,11 +67323,11 @@ function useBuildingLevelController() {
67219
67323
  }
67220
67324
  async function batchUpdateByIds(req, res, next) {
67221
67325
  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)
67326
+ const schema2 = Joi147.array().items(
67327
+ Joi147.object({
67328
+ _id: Joi147.string().hex().length(24).required(),
67329
+ value: Joi147.object({
67330
+ name: Joi147.string().optional().allow("", null)
67227
67331
  }).required()
67228
67332
  })
67229
67333
  );
@@ -67246,9 +67350,9 @@ function useBuildingLevelController() {
67246
67350
  }
67247
67351
  async function getBuildingLevelList(req, res, next) {
67248
67352
  try {
67249
- const schema2 = Joi146.object({
67250
- site: Joi146.string().hex().length(24).required(),
67251
- block: Joi146.string().hex().length(24).required()
67353
+ const schema2 = Joi147.object({
67354
+ site: Joi147.string().hex().length(24).required(),
67355
+ block: Joi147.string().hex().length(24).required()
67252
67356
  });
67253
67357
  const { error, value } = schema2.validate({
67254
67358
  site: req.params.siteId,