82 lines
4.6 KiB
MySQL
82 lines
4.6 KiB
MySQL
|
|
-- 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);
|