# ListNotificationCategories

## Overview

ListNotificationCategories returns the host-seeded NotificationCategory catalog used by the preferences UI and the dispatcher. Each row carries the category's id, display name, and the `optOutAllowed` flag that distinguishes optional broadcast-style categories (announcements, reminders) from transactional categories (invoice approval, supplier suspension) that always reach the recipient regardless of preference rows.

## Business Rules

- Accepts optional pagination input (`limit`, `offset`, `orderBy`, `orderDirection`), consistent with the module's other list queries; with no input it returns the full seeded catalog ordered by `categoryId`
- Returns the seeded NotificationCategory rows as a paginated result
- Each row carries `categoryId`, `displayName`, and `optOutAllowed`
- Categories cannot be created by end users — the catalog is seeded by the host application, so the result reflects whatever is currently seeded
- Returns an empty list only when the catalog has not been seeded; in normal operation the result is non-empty

## Process Flow

```mermaid
flowchart TD
    A[Receive request with optional pagination] --> B[Load NotificationCategory rows ordered by orderBy, applying limit/offset]
    B --> C[Return paginated list]
```

## External Dependencies

- None

## Error Scenarios

- **NO_MATCH**: No matching row exists for the supplied input; null or empty result is returned

> Returning `NO_MATCH` is a normal empty/null result rather than a thrown error — the query returns the null/empty value and does not raise `NoMatchError`.

## Test Cases

- returns every seeded NotificationCategory
- returns each row with `optOutAllowed = true` for optional categories (announcements, rfq-updates, etc.)
- returns each row with `optOutAllowed = false` for transactional categories (invoice-updates, supplier-lifecycle, etc.)
- returns an empty list when the catalog has not been seeded
- honors `limit`/`offset` pagination and reports `hasNextPage` when more rows remain
