49 lines
3.3 KiB
SQL
49 lines
3.3 KiB
SQL
-- 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';
|