@7365admin1/core 3.72.1-staging.326 → 3.72.1-staging.327

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.
@@ -0,0 +1,5 @@
1
+ ---
2
+ "@7365admin1/core": minor
3
+ ---
4
+
5
+ Add the `inventory` notification category (in-app and push), offered to roles holding any `inventory:*` permission, for API-core's inventory alerts: a request waiting for approval, a decided request, and low stock.
package/dist/index.d.ts CHANGED
@@ -10567,12 +10567,12 @@ declare function useNewDashboardRepo(): {
10567
10567
  percentage: number | null;
10568
10568
  };
10569
10569
  supplyAlert: {
10570
+ thresholdUnavailableReason?: string | undefined;
10570
10571
  items: {
10571
10572
  name: any;
10572
10573
  qty: any;
10573
10574
  }[];
10574
- basis: "lowest-quantity";
10575
- thresholdUnavailableReason: string;
10575
+ basis: "lowest-quantity" | "below-alert-level";
10576
10576
  };
10577
10577
  taskCompleted: {
10578
10578
  completed: any;
package/dist/index.js CHANGED
@@ -9680,6 +9680,20 @@ var NOTIFICATION_CATEGORIES = [
9680
9680
  vendorDefault: true,
9681
9681
  rendered: true
9682
9682
  },
9683
+ // Inventory (2026-09-17). Sent from `iservice365-API-core`'s inventory
9684
+ // module: a stock request waiting for approval and stock falling to its alert
9685
+ // level go to that store's staff; a decided request goes to the person who
9686
+ // asked. The caller checks `rendered` before it sends, so the sender and this
9687
+ // switch cannot land out of order.
9688
+ {
9689
+ key: "inventory",
9690
+ label: "Inventory",
9691
+ description: "When a stock request needs your approval or has been decided, or stock you look after runs low.",
9692
+ channels: { inApp: true, push: true, email: false },
9693
+ channelNote: { email: NO_EMAIL_RECIPIENT },
9694
+ permissionResources: ["inventory"],
9695
+ rendered: true
9696
+ },
9683
9697
  {
9684
9698
  key: "serviceProviderInvite",
9685
9699
  label: "Service Provider Invitations",
@@ -77824,6 +77838,7 @@ function highSeverityIncidentCount(severities) {
77824
77838
  ).length;
77825
77839
  }
77826
77840
  var SUPPLY_BASIS_LOWEST_QUANTITY = "lowest-quantity";
77841
+ var SUPPLY_BASIS_BELOW_ALERT_LEVEL = "below-alert-level";
77827
77842
  var SUPPLY_THRESHOLD_NOT_IN_MODEL = "Supplies do not record a stock threshold, so these are the lowest-quantity items rather than items below a level.";
77828
77843
 
77829
77844
  // src/repositories/new-dashboard.repo.ts
@@ -78682,6 +78697,32 @@ function useNewDashboardRepo() {
78682
78697
  { $unwind: { path: "$scheduleDoc", preserveNullAndEmptyArrays: false } }
78683
78698
  ];
78684
78699
  }
78700
+ async function lowStockItems(site, serviceType) {
78701
+ const stores = await db2.collection("inventory.stores").find({ sites: site, status: "active" }, { projection: { _id: 1 } }).toArray();
78702
+ if (stores.length) {
78703
+ const items2 = await db2.collection("inventory.items").aggregate([
78704
+ {
78705
+ $match: {
78706
+ store: { $in: stores.map((store) => store._id) },
78707
+ status: "active",
78708
+ reorderLevel: { $gt: 0 },
78709
+ $expr: { $lte: ["$onHand", "$reorderLevel"] }
78710
+ }
78711
+ },
78712
+ { $sort: { onHand: 1 } },
78713
+ { $limit: 5 },
78714
+ { $project: { _id: 1, name: 1, qty: "$onHand" } }
78715
+ ]).toArray();
78716
+ return { items: items2, basis: SUPPLY_BASIS_BELOW_ALERT_LEVEL };
78717
+ }
78718
+ const items = await supplyCollection.aggregate([
78719
+ { $match: { site, serviceType, status: "active" } },
78720
+ { $sort: { qty: 1 } },
78721
+ { $limit: 3 },
78722
+ { $project: { _id: 1, name: 1, qty: 1 } }
78723
+ ]).toArray();
78724
+ return { items, basis: SUPPLY_BASIS_LOWEST_QUANTITY };
78725
+ }
78685
78726
  async function getServiceDashboard({
78686
78727
  site,
78687
78728
  serviceType,
@@ -78739,12 +78780,7 @@ function useNewDashboardRepo() {
78739
78780
  }
78740
78781
  }
78741
78782
  ]).toArray(),
78742
- supplyCollection.aggregate([
78743
- { $match: { site, serviceType, status: "active" } },
78744
- { $sort: { qty: 1 } },
78745
- { $limit: 3 },
78746
- { $project: { _id: 1, name: 1, qty: 1 } }
78747
- ]).toArray(),
78783
+ lowStockItems(site, serviceType),
78748
78784
  areaChecklistCollection.aggregate([
78749
78785
  ...areaChecklistScheduleLookup(site, serviceType, periodRange),
78750
78786
  {
@@ -78806,7 +78842,7 @@ function useNewDashboardRepo() {
78806
78842
  )
78807
78843
  },
78808
78844
  supplyAlert: {
78809
- items: supplyAlertReport.map((item) => ({
78845
+ items: supplyAlertReport.items.map((item) => ({
78810
78846
  name: item.name,
78811
78847
  qty: item.qty
78812
78848
  })),
@@ -78814,8 +78850,8 @@ function useNewDashboardRepo() {
78814
78850
  // with no threshold, because `site.supplies` records no stock level to
78815
78851
  // compare against. Naming the ordering stops 900 gloves being drawn as
78816
78852
  // a warning. No threshold is invented here.
78817
- basis: SUPPLY_BASIS_LOWEST_QUANTITY,
78818
- thresholdUnavailableReason: SUPPLY_THRESHOLD_NOT_IN_MODEL
78853
+ basis: supplyAlertReport.basis,
78854
+ ...supplyAlertReport.basis === SUPPLY_BASIS_LOWEST_QUANTITY ? { thresholdUnavailableReason: SUPPLY_THRESHOLD_NOT_IN_MODEL } : {}
78819
78855
  },
78820
78856
  taskCompleted: {
78821
78857
  completed: tFacet.completed[0]?.count ?? 0,