# 21 — Notifications & Alerts **Status**: Not Started **Depends On**: 02 — Stock Ledger, 12 — Store Management, 08 — Sales Agent Controls --- ## Goal Covers [mainPlan.md §15](./mainPlan.md#15-notifications--alerts) in full — a cross-cutting delivery mechanism (email/SMS/push) triggered by events other steps already produce. --- ## Background / Context No notification channel exists in this codebase today. This step is purely the delivery mechanism and trigger wiring; the underlying conditions it watches for are already defined elsewhere (reorder point in [02_stock_ledger.md](./02_stock_ledger.md), credit limit in [12_store_management.md](./12_store_management.md), route deviation logic in [09_fraud_controls.md](./09_fraud_controls.md)). --- ## Data Model Changes ### Notification `RecipientUserId`, `Type`, `Payload` (JSON), `Channel` (`Email`, `SMS`, `Push`, `InApp`), `SentAt`, `ReadAt` (nullable). --- ## API Endpoints | Function reference | Endpoint intent | |---|---| | `sendLowStockAlert(warehouseId, sku)` | Internal — triggered when a stock movement crosses the reorder point set in [02_stock_ledger.md](./02_stock_ledger.md) | | `sendCreditLimitBreachAlert(storeId)` | Internal — triggered on order/invoice creation when `Store.OutstandingBalance` exceeds `Store.CreditLimit` | | `sendApprovalPendingNotification(approverId, requestId)` | Internal — triggered by `submitOrderForApproval` ([08_sales_agent_controls.md](./08_sales_agent_controls.md)) and return approval ([18_returns_claims.md](./18_returns_claims.md)) | | `sendRouteDeviationAlert(routeId, salesRepId)` | Internal — triggered from [09_fraud_controls.md](./09_fraud_controls.md)'s anomaly flag | | — | `GET /api/notifications` — recipient's own notification inbox | | — | `PUT /api/notifications/{id}/read` | --- ## Business Rules - Every `send*` function in §15 is a trigger, not a user-facing endpoint — the only client-facing endpoints are inbox read/list. - Notification delivery failures (e.g. SMS provider down) must not roll back the business transaction that triggered them — fire-and-forget, logged separately. --- ## Open Questions - Which channels are actually needed at launch — in-app only, or SMS/email/push from day one? This significantly changes the infrastructure needed (third-party provider integration, see [22_integration_api.md](./22_integration_api.md)). --- ## Implementation Notes > Fill this section in during planning discussion before writing any code.