82 lines
4.6 KiB
SQL
82 lines
4.6 KiB
SQL
-- 0014_recurring_rules — повторяющиеся заявки по расписанию.
|
||
--
|
||
-- Зачем: периодические работы («осмотр вентиляции раз в 3 месяца»)
|
||
-- заводятся один раз правилом, а фоновый планировщик сам создаёт
|
||
-- заявку, когда истекает интервал. Правило — шаблон будущей заявки
|
||
-- (объект, категория, описание, приоритет) плюс интервал в месяцах.
|
||
--
|
||
-- Кто владеет: client_id — клиент-владелец (заявка создаётся от его
|
||
-- имени, как ручная); created_by — кто завёл правило (админ или сам
|
||
-- клиент). Правило живёт в проекте и объекте: каскады унесут его
|
||
-- вместе с ними (удаление проекта админом из 0013).
|
||
--
|
||
-- Повторный запуск: правило созрело, но прошлая заявка ещё не
|
||
-- закрыта — новую не создаём (ждём закрытия, без дублей). Состояние
|
||
-- хранится в last_run_at (когда последний раз срабатывали) и в
|
||
-- recurring_runs (история: какая заявка создана по какому правилу).
|
||
--
|
||
-- Применённый файл не редактировать (checksum в schema_migrations).
|
||
|
||
-- ============ recurring_rules ============
|
||
|
||
CREATE TABLE IF NOT EXISTS recurring_rules (
|
||
id bigserial PRIMARY KEY,
|
||
-- Владелец будущих заявок: client_id проекта продублирован, чтобы
|
||
-- заявка создавалась без JOIN и составной FK projects был соблюдён.
|
||
client_id uuid NOT NULL REFERENCES profiles (id),
|
||
project_id bigint NOT NULL REFERENCES projects (id) ON DELETE CASCADE,
|
||
object_id bigint NOT NULL REFERENCES project_objects (id) ON DELETE CASCADE,
|
||
|
||
-- Шаблон заявки (те же колонки, что в tickets).
|
||
category text NOT NULL,
|
||
description text NOT NULL,
|
||
priority text NOT NULL DEFAULT 'normal',
|
||
floor text,
|
||
|
||
-- Расписание: 3 — квартальный осмотр, 12 — годовой.
|
||
interval_months int NOT NULL,
|
||
is_active boolean NOT NULL DEFAULT true,
|
||
|
||
-- Когда последний раз срабатывали; NULL — ещё ни разу.
|
||
last_run_at timestamptz,
|
||
|
||
created_by uuid REFERENCES profiles (id),
|
||
created_at timestamptz NOT NULL DEFAULT now(),
|
||
|
||
CONSTRAINT recurring_rules_category_check
|
||
CHECK (category IN ('electric', 'plumbing', 'climate', 'elevator', 'other')),
|
||
CONSTRAINT recurring_rules_priority_check
|
||
CHECK (priority IN ('low', 'normal', 'high')),
|
||
CONSTRAINT recurring_rules_interval_check
|
||
CHECK (interval_months >= 1),
|
||
|
||
-- Правило обязано жить в объекте своего проекта (то же ядро, что
|
||
-- у заявки): составной FK держит объект и проект согласованными.
|
||
CONSTRAINT recurring_rules_object_project_fk
|
||
FOREIGN KEY (object_id, project_id)
|
||
REFERENCES project_objects (id, project_id),
|
||
CONSTRAINT recurring_rules_project_client_fk
|
||
FOREIGN KEY (project_id, client_id)
|
||
REFERENCES projects (id, client_id)
|
||
);
|
||
|
||
-- Лента правил: клиент — свои, админ — все проекты.
|
||
CREATE INDEX IF NOT EXISTS recurring_rules_client_idx ON recurring_rules (client_id);
|
||
CREATE INDEX IF NOT EXISTS recurring_rules_project_idx ON recurring_rules (project_id);
|
||
-- Отбор созревших правил поллером.
|
||
CREATE INDEX IF NOT EXISTS recurring_rules_due_idx
|
||
ON recurring_rules (last_run_at) WHERE is_active;
|
||
|
||
-- ============ recurring_runs ============
|
||
|
||
-- История срабатываний: аудит «кто и когда создал авто-заявку».
|
||
CREATE TABLE IF NOT EXISTS recurring_runs (
|
||
id bigserial PRIMARY KEY,
|
||
rule_id bigint NOT NULL REFERENCES recurring_rules (id) ON DELETE CASCADE,
|
||
-- NULL, если созданную заявку потом удалили каскадом (проект).
|
||
ticket_id bigint REFERENCES tickets (id) ON DELETE SET NULL,
|
||
run_at timestamptz NOT NULL DEFAULT now()
|
||
);
|
||
|
||
CREATE INDEX IF NOT EXISTS recurring_runs_rule_idx ON recurring_runs (rule_id, run_at DESC);
|