feat(notificaciones): one send log across servicios and pólizas
Renewal avisos left behind only a `RenewalNotice` row, whose sole job is gating: a row with `sentAt` drops the policy off the pending list. It cannot represent a failed send or a customer with no address, so the Pólizas tab had no "Registro de envíos" to show and a sent notice simply vanished from the list. Renewals now write `email_notification_log` — the same table the four bulk jobs write — as `RENEWAL_NOTICE` / `POLICIES`, with rows for failures and no-email skips too. `RenewalNotice` keeps its gating role unchanged; the two are complementary, not redundant. - extend `EmailNotificationType` (+RENEWAL_NOTICE) and `EmailNotificationServicio` (+POLICIES); `level` now carries the aviso generation on renewal rows, so every reader must branch on the type first (`notificationLevelLabel()` is the one place that lives) - backfill emailed notices (`channel = 'EMAIL'`) into the log; MAIL-channel rows are legacy printed letters and are deliberately left out - extract `NotificationLogService`/`NotificationLogModule` as the single writer, so a feature that sends mail records it without pulling the bulk-job pipelines into its module - `GET /notifications/log` and `/stats` take a comma-separated `servicio` list; each tab reads its own slice. This also fixes the "Omitidos" view, which mapped to no filter at all and showed every row - share one `NotificationLogPanel` between both tabs - pass SES_* / NOTIFICATION_ADMIN_EMAILS through the galactus compose, which was missing them entirely — mail is runtime config, not a CI secret, and the prod image sets NODE_ENV=production so a blank config fails loudly instead of falling back to stdout Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -93,6 +93,24 @@ correlation.
|
||||
|
||||
Indexes: `(sendDate)`, `(notificationType, sendDate)`, `(customerId, sendDate)`.
|
||||
|
||||
**This table is not job-specific.** Insurance renewal avisos
|
||||
(`RenewalsService`, see [`RENEWAL_NOTICES.md`](RENEWAL_NOTICES.md)) write
|
||||
here too, as `notificationType = RENEWAL_NOTICE` /
|
||||
`servicio = POLICIES` — one send history for the whole platform rather
|
||||
than one per feature. `NotificationLogService` is the only writer;
|
||||
anything that sends mail goes through it.
|
||||
|
||||
`level` is therefore per-type and cannot be read without its
|
||||
`notificationType`: 0/1 (yellow/red) on `ACCOUNT_STATUS`, the aviso
|
||||
generation 1/2/3 on `RENEWAL_NOTICE`, null elsewhere. On the web side
|
||||
`notificationLevelLabel()` is the only place that branch lives.
|
||||
|
||||
Renewals keep their own `renewal_notices` row as well. The two are not
|
||||
redundant: `renewal_notices` is *gating* state (one row per
|
||||
policy+generation, "already notified" — it drives the pending list),
|
||||
while this log is *history* (every attempt, including the failures and
|
||||
no-email skips a gating row cannot represent).
|
||||
|
||||
### `account_status_history`
|
||||
|
||||
Mirrors the legacy `utility_dbo.send_account_status_history` table:
|
||||
@@ -120,12 +138,25 @@ Without SES_* the API still boots and `MailService` falls back to stdout
|
||||
in dev (`NODE_ENV !== "production"`). In production every send throws
|
||||
`ServiceUnavailableException` and the row is recorded as `FAILED`.
|
||||
|
||||
These are **runtime** config, set in the deployed stack's env file on the
|
||||
host (`deploy/jorgecuadros-app.env.example` documents the full set) — not
|
||||
Gitea Actions secrets. The build never sends mail; only the running
|
||||
container does, and the production image sets `NODE_ENV=production`, so a
|
||||
blank SES config fails loudly rather than falling back to stdout.
|
||||
|
||||
## UI
|
||||
|
||||
`/notificaciones` (gated on `notification:send`) — four trigger cards,
|
||||
a debug/ignoreDayRestriction/useEmailLimit flags panel, a transport
|
||||
status header, and a paginated log table. STAFF users see the log
|
||||
read-only.
|
||||
`/notificaciones`, two tabs over the one log:
|
||||
|
||||
- **Servicios** (`notification:send`) — four trigger cards, a
|
||||
debug/ignoreDayRestriction/useEmailLimit flags panel, a transport status
|
||||
header. Reads the `CUSTOMERS` + `TRUST` slice.
|
||||
- **Pólizas** (`renewal:send`) — pending avisos and the manual sweep.
|
||||
Reads the `POLICIES` slice.
|
||||
|
||||
Both render the same `NotificationLogPanel` ("Registro de envíos"), which
|
||||
filters by servicio and by view (todos / enviados / fallidos / omitidos).
|
||||
STAFF users see the Servicios log read-only.
|
||||
|
||||
## Cron (future)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user