@7365admin1/core 3.76.0 → 3.77.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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # @iservice365/core
2
2
 
3
+ ## 3.77.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 09c259b: 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.
8
+
3
9
  ## 3.76.0
4
10
 
5
11
  ### Minor Changes
package/dist/index.d.ts CHANGED
@@ -10452,12 +10452,12 @@ declare function useNewDashboardRepo(): {
10452
10452
  percentage: number | null;
10453
10453
  };
10454
10454
  supplyAlert: {
10455
+ thresholdUnavailableReason?: string | undefined;
10455
10456
  items: {
10456
10457
  name: any;
10457
10458
  qty: any;
10458
10459
  }[];
10459
- basis: "lowest-quantity";
10460
- thresholdUnavailableReason: string;
10460
+ basis: "lowest-quantity" | "below-alert-level";
10461
10461
  };
10462
10462
  taskCompleted: {
10463
10463
  completed: any;
package/dist/index.js CHANGED
@@ -9644,6 +9644,20 @@ var NOTIFICATION_CATEGORIES = [
9644
9644
  vendorDefault: true,
9645
9645
  rendered: true
9646
9646
  },
9647
+ // Inventory (2026-09-17). Sent from `iservice365-API-core`'s inventory
9648
+ // module: a stock request waiting for approval and stock falling to its alert
9649
+ // level go to that store's staff; a decided request goes to the person who
9650
+ // asked. The caller checks `rendered` before it sends, so the sender and this
9651
+ // switch cannot land out of order.
9652
+ {
9653
+ key: "inventory",
9654
+ label: "Inventory",
9655
+ description: "When a stock request needs your approval or has been decided, or stock you look after runs low.",
9656
+ channels: { inApp: true, push: true, email: false },
9657
+ channelNote: { email: NO_EMAIL_RECIPIENT },
9658
+ permissionResources: ["inventory"],
9659
+ rendered: true
9660
+ },
9647
9661
  {
9648
9662
  key: "serviceProviderInvite",
9649
9663
  label: "Service Provider Invitations",
@@ -76531,6 +76545,7 @@ function highSeverityIncidentCount(severities) {
76531
76545
  ).length;
76532
76546
  }
76533
76547
  var SUPPLY_BASIS_LOWEST_QUANTITY = "lowest-quantity";
76548
+ var SUPPLY_BASIS_BELOW_ALERT_LEVEL = "below-alert-level";
76534
76549
  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.";
76535
76550
 
76536
76551
  // src/repositories/new-dashboard.repo.ts
@@ -77389,6 +77404,32 @@ function useNewDashboardRepo() {
77389
77404
  { $unwind: { path: "$scheduleDoc", preserveNullAndEmptyArrays: false } }
77390
77405
  ];
77391
77406
  }
77407
+ async function lowStockItems(site, serviceType) {
77408
+ const stores = await db2.collection("inventory.stores").find({ sites: site, status: "active" }, { projection: { _id: 1 } }).toArray();
77409
+ if (stores.length) {
77410
+ const items2 = await db2.collection("inventory.items").aggregate([
77411
+ {
77412
+ $match: {
77413
+ store: { $in: stores.map((store) => store._id) },
77414
+ status: "active",
77415
+ reorderLevel: { $gt: 0 },
77416
+ $expr: { $lte: ["$onHand", "$reorderLevel"] }
77417
+ }
77418
+ },
77419
+ { $sort: { onHand: 1 } },
77420
+ { $limit: 5 },
77421
+ { $project: { _id: 1, name: 1, qty: "$onHand" } }
77422
+ ]).toArray();
77423
+ return { items: items2, basis: SUPPLY_BASIS_BELOW_ALERT_LEVEL };
77424
+ }
77425
+ const items = await supplyCollection.aggregate([
77426
+ { $match: { site, serviceType, status: "active" } },
77427
+ { $sort: { qty: 1 } },
77428
+ { $limit: 3 },
77429
+ { $project: { _id: 1, name: 1, qty: 1 } }
77430
+ ]).toArray();
77431
+ return { items, basis: SUPPLY_BASIS_LOWEST_QUANTITY };
77432
+ }
77392
77433
  async function getServiceDashboard({
77393
77434
  site,
77394
77435
  serviceType,
@@ -77446,12 +77487,7 @@ function useNewDashboardRepo() {
77446
77487
  }
77447
77488
  }
77448
77489
  ]).toArray(),
77449
- supplyCollection.aggregate([
77450
- { $match: { site, serviceType, status: "active" } },
77451
- { $sort: { qty: 1 } },
77452
- { $limit: 3 },
77453
- { $project: { _id: 1, name: 1, qty: 1 } }
77454
- ]).toArray(),
77490
+ lowStockItems(site, serviceType),
77455
77491
  areaChecklistCollection.aggregate([
77456
77492
  ...areaChecklistScheduleLookup(site, serviceType, periodRange),
77457
77493
  {
@@ -77513,7 +77549,7 @@ function useNewDashboardRepo() {
77513
77549
  )
77514
77550
  },
77515
77551
  supplyAlert: {
77516
- items: supplyAlertReport.map((item) => ({
77552
+ items: supplyAlertReport.items.map((item) => ({
77517
77553
  name: item.name,
77518
77554
  qty: item.qty
77519
77555
  })),
@@ -77521,8 +77557,8 @@ function useNewDashboardRepo() {
77521
77557
  // with no threshold, because `site.supplies` records no stock level to
77522
77558
  // compare against. Naming the ordering stops 900 gloves being drawn as
77523
77559
  // a warning. No threshold is invented here.
77524
- basis: SUPPLY_BASIS_LOWEST_QUANTITY,
77525
- thresholdUnavailableReason: SUPPLY_THRESHOLD_NOT_IN_MODEL
77560
+ basis: supplyAlertReport.basis,
77561
+ ...supplyAlertReport.basis === SUPPLY_BASIS_LOWEST_QUANTITY ? { thresholdUnavailableReason: SUPPLY_THRESHOLD_NOT_IN_MODEL } : {}
77526
77562
  },
77527
77563
  taskCompleted: {
77528
77564
  completed: tFacet.completed[0]?.count ?? 0,