# Dashboard & Notifications

This guide explains how the **customer dashboard** stays consistent and how **in-app notifications** are generated.

## Dashboard “single read model” (`/api/me/status`)

To keep business logic out of the frontend, the Portal uses a single BFF endpoint:

- **Endpoint**: `GET /api/me/status`
- **Purpose**: Return a consistent snapshot of the customer’s current state (summary + tasks + gating signals).
- **Domain type**: `@customer-portal/domain/dashboard` → `meStatusSchema`

The response includes:

- **`summary`**: Same shape as `GET /api/me/summary` (stats, next invoice, activity).
- **`internetEligibility`**: Internet eligibility status/details for the logged-in customer.
- **`residenceCardVerification`**: Residence card verification status/details.
- **`paymentMethods.totalCount`**: Count of stored payment methods (or `null` if unavailable).
- **`tasks[]`**: A prioritized list of dashboard tasks (invoice due, add payment method, order in progress, eligibility pending, IDV rejected, onboarding).

Portal UI maps task `type` → icon locally; everything else (priority, copy, links) is computed server-side.

## In-app Notifications

In-app notifications are stored in Postgres and fetched via the Notifications API. Notifications use domain templates in:

- `packages/domain/notifications/schema.ts`

### All Notification Types

| Type                      | Title                                      | Created By             | Trigger                         |
| ------------------------- | ------------------------------------------ | ---------------------- | ------------------------------- |
| `ELIGIBILITY_ELIGIBLE`    | "Good news! Internet service is available" | Platform Event         | Eligibility status → Eligible   |
| `ELIGIBILITY_INELIGIBLE`  | "Internet service not available"           | Platform Event         | Eligibility status → Ineligible |
| `VERIFICATION_VERIFIED`   | "ID verification complete"                 | Platform Event         | Verification status → Verified  |
| `VERIFICATION_REJECTED`   | "ID verification requires attention"       | Platform Event         | Verification status → Rejected  |
| `ORDER_APPROVED`          | "Order approved"                           | Fulfillment flow       | Order approved in Salesforce    |
| `ORDER_ACTIVATED`         | "Service activated"                        | Fulfillment flow       | WHMCS provisioning complete     |
| `ORDER_FAILED`            | "Order requires attention"                 | Fulfillment flow       | Fulfillment error               |
| `CANCELLATION_SCHEDULED`  | "Cancellation scheduled"                   | Cancellation flow      | Customer requests cancellation  |
| `CANCELLATION_COMPLETE`   | "Service cancelled"                        | _(Not implemented)_    | —                               |
| `PAYMENT_METHOD_EXPIRING` | "Payment method expiring soon"             | _(Not implemented)_    | —                               |
| `INVOICE_DUE`             | "Invoice due"                              | Dashboard status check | Invoice due within 7 days       |
| `SYSTEM_ANNOUNCEMENT`     | "System announcement"                      | _(Not implemented)_    | —                               |

### Eligibility & Verification Notifications

These are triggered by Salesforce Platform Events:

1. **Salesforce Flow** fires Platform Event when `Internet_Eligibility_Status__c` or `Id_Verification_Status__c` changes
2. **BFF subscriber** receives the event and extracts status fields
3. **Notification handler** creates notification only for final states:
   - Eligibility: `Eligible` or `Ineligible` (not `Pending`)
   - Verification: `Verified` or `Rejected` (not `Submitted`)

**Important:** The Salesforce Flow must use `ISCHANGED()` to only include status fields when they actually changed. Otherwise, notifications would be created on every account update.

See `docs/integrations/salesforce/platform-events.md` for Platform Event configuration.

### Order Notifications

Created during the fulfillment workflow in:

- `apps/bff/src/modules/orders/services/order-fulfillment-orchestrator.service.ts`

The notification `sourceId` uses the Salesforce Order ID to prevent duplicates during retries.

### Cancellation Notifications

Created when cancellation request is submitted:

- Internet: `apps/bff/src/modules/subscriptions/internet-management/services/internet-cancellation.service.ts`
- SIM: `apps/bff/src/modules/subscriptions/sim-management/services/sim-cancellation.service.ts`

### Invoice Due Notifications

Created opportunistically when dashboard status is requested (`GET /api/me/status`) if an invoice is due within 7 days or overdue.

### Dedupe Behavior

Notifications dedupe is enforced in:

- `apps/bff/src/modules/notifications/notifications.service.ts`

| Type Category                                | Dedupe Window | Logic                    |
| -------------------------------------------- | ------------- | ------------------------ |
| Most types                                   | 1 hour        | Same `type` + `sourceId` |
| Invoice due, payment expiring, announcements | 24 hours      | Same `type` + `sourceId` |

### Action URLs

Notification templates use authenticated Portal routes:

- `/account/orders` - Order notifications
- `/account/services` - Activation/cancellation notifications
- `/account/services/internet` - Eligibility notifications
- `/account/settings/verification` - Verification notifications
- `/account/billing/invoices` - Invoice notifications
