axe/internal/db/migrations/0011_telegram_notifications.sql
2026-10-18 22:07:25 +03:00

49 lines
3.3 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- 0011_telegram_notifications — уведомления в Telegram о заявках,
-- которые простояли в статусе 'new' дольше 24 часов.
--
-- Куда слать — profiles.telegram_target, одно поле и два способа его
-- заполнить:
-- * числовой chat_id — записывает long-polling поллер, когда человек
-- написал боту /start <код> из раздела «Настройки» (личная привязка);
-- * @группа или @канал — вводит сам пользователь (бот обязан быть
-- добавлен в этот чат; личный @ник боту недоступен, пока человек
-- сам боту не напишет — поэтому личная привязка и через код).
-- Пусто/NULL — уведомления этому пользователю не приходят.
--
-- Дедуп — tickets.tg_notified_at: когда уходило последнее сообщение.
-- Повторять можно, если поле NULL или старше порога (24 ч): напоминание
-- уходит раз в сутки, пока заявка остаётся 'new'. Как только её взяли —
-- условие отваливается само; поле не чистим, чтобы после возврата в
-- 'new' отсчёт начался заново.
--
-- Коды привязки — одноразовые и короткоживущие (15 минут). В таблице
-- лежит только sha256 кода, как и токены сброса пароля (0007): утекшая
-- база не даёт привязать чужой чат — по хешу код не восстановить.
-- Выпуск нового кода гасит прежние неиспользованные (см. CreateBindCode).
--
-- Применённый файл не редактировать (checksum в schema_migrations).
ALTER TABLE profiles ADD COLUMN IF NOT EXISTS telegram_target text;
ALTER TABLE tickets ADD COLUMN IF NOT EXISTS tg_notified_at timestamptz;
CREATE TABLE IF NOT EXISTS telegram_bind_codes (
user_id uuid NOT NULL REFERENCES profiles (id) ON DELETE CASCADE,
-- sha256 кода в hex; сам код показывается пользователю один раз
code_hash text PRIMARY KEY,
created_at timestamptz NOT NULL DEFAULT now(),
expires_at timestamptz NOT NULL,
used_at timestamptz,
CONSTRAINT telegram_bind_codes_expiry CHECK (expires_at > created_at)
);
-- У одного пользователя обычно один живой код; гашение прежних идёт
-- по его строкам, чистка — по expires_at.
CREATE INDEX IF NOT EXISTS telegram_bind_codes_user_idx
ON telegram_bind_codes (user_id, created_at);
-- Кандидаты на уведомление — все ещё не взятые заявки: отбор по
-- created_at внутри статуса 'new' (частичный индекс держит запрос дешёвым).
CREATE INDEX IF NOT EXISTS tickets_new_created_idx
ON tickets (created_at) WHERE status = 'new';