Files
WhatIDo/db/migration.sql
T

150 lines
5.5 KiB
SQL

CREATE TABLE IF NOT EXISTS students (
id SERIAL PRIMARY KEY,
name VARCHAR(150) NOT NULL UNIQUE,
created_at TIMESTAMPTZ DEFAULT now()
);
ALTER TABLE students ADD COLUMN IF NOT EXISTS group_id INT REFERENCES groups(id);
CREATE TABLE IF NOT EXISTS settings (
key TEXT PRIMARY KEY,
value TEXT
);
INSERT INTO settings (key, value) VALUES ('spam_interval_min', '30')
ON CONFLICT (key) DO NOTHING;
INSERT INTO settings (key, value) VALUES ('ai_prompt', 'Ты — редактор текстов для педагогического журнала. Исправь грамматические, орфографические и пунктуационные ошибки. Сохрани смысл и стиль. Верни ТОЛЬКО исправленный текст, без пояснений.')
ON CONFLICT (key) DO NOTHING;
CREATE TABLE IF NOT EXISTS share_links (
id SERIAL PRIMARY KEY,
token VARCHAR(40) UNIQUE NOT NULL,
name VARCHAR(200) NOT NULL,
group_id INT REFERENCES groups(id),
student_name VARCHAR(150),
date_from DATE,
date_to DATE,
created_at TIMESTAMPTZ DEFAULT now()
);
ALTER TABLE share_links ADD COLUMN IF NOT EXISTS message TEXT;
ALTER TABLE share_links ADD COLUMN IF NOT EXISTS link_url VARCHAR(500);
DO $$
BEGIN
INSERT INTO students (name)
SELECT DISTINCT student_name FROM entries WHERE student_name IS NOT NULL AND student_name <> ''
ON CONFLICT (name) DO NOTHING;
END $$;
CREATE TABLE IF NOT EXISTS project_files (
id SERIAL PRIMARY KEY,
entry_id INT NOT NULL REFERENCES entries(id) ON DELETE CASCADE,
token VARCHAR(64),
path VARCHAR(255) NOT NULL,
name VARCHAR(255) NOT NULL,
created_at TIMESTAMPTZ DEFAULT now()
);
UPDATE project_files SET token = md5(random()::text || clock_timestamp()::text) WHERE token IS NULL;
ALTER TABLE project_files ALTER COLUMN token SET NOT NULL;
CREATE UNIQUE INDEX IF NOT EXISTS project_files_token_key ON project_files(token);
ALTER TABLE project_files ALTER COLUMN entry_id DROP NOT NULL;
ALTER TABLE project_files ADD COLUMN IF NOT EXISTS detached_at TIMESTAMPTZ;
CREATE TABLE IF NOT EXISTS entry_photos (
id SERIAL PRIMARY KEY,
entry_id INT NOT NULL REFERENCES entries(id) ON DELETE CASCADE,
photo_path VARCHAR(255) NOT NULL,
caption TEXT,
sort_order INT DEFAULT 0,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE INDEX IF NOT EXISTS idx_entry_photos_entry_id ON entry_photos(entry_id);
ALTER TABLE entries ADD COLUMN IF NOT EXISTS deleted_at TIMESTAMPTZ;
ALTER TABLE entries ADD COLUMN IF NOT EXISTS description_original TEXT;
ALTER TABLE entries ADD COLUMN IF NOT EXISTS description_ai TEXT;
ALTER TABLE entries ADD COLUMN IF NOT EXISTS ai_status VARCHAR(20) NOT NULL DEFAULT 'pending';
ALTER TABLE entries ADD COLUMN IF NOT EXISTS ai_checked_at TIMESTAMPTZ;
ALTER TABLE entries ADD COLUMN IF NOT EXISTS ai_error TEXT;
CREATE INDEX IF NOT EXISTS idx_entries_ai_pending ON entries(id) WHERE ai_status = 'pending' AND deleted_at IS NULL;
INSERT INTO settings (key, value) VALUES ('ai_autocheck_enabled', 'true')
ON CONFLICT (key) DO NOTHING;
DO $$
BEGIN
IF NOT EXISTS (SELECT 1 FROM settings WHERE key = 'ai_autocheck_migrated') THEN
UPDATE entries SET description_original = description WHERE description_original IS NULL;
UPDATE entries SET ai_status = 'skipped' WHERE ai_status = 'pending';
INSERT INTO settings (key, value) VALUES ('ai_autocheck_migrated', '1');
END IF;
END $$;
CREATE TABLE IF NOT EXISTS branches (
id SERIAL PRIMARY KEY,
name VARCHAR(200) NOT NULL UNIQUE,
address TEXT,
phone VARCHAR(50),
created_at TIMESTAMPTZ DEFAULT now()
);
ALTER TABLE groups ADD COLUMN IF NOT EXISTS branch_id INT REFERENCES branches(id) ON DELETE SET NULL;
ALTER TABLE groups ADD COLUMN IF NOT EXISTS day_of_week INT;
ALTER TABLE groups ADD COLUMN IF NOT EXISTS time_start TIME;
ALTER TABLE groups ADD COLUMN IF NOT EXISTS time_end TIME;
ALTER TABLE groups ADD COLUMN IF NOT EXISTS cover_path VARCHAR(255);
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
username VARCHAR(100) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL,
name VARCHAR(150),
role VARCHAR(20) NOT NULL DEFAULT 'tutor' CHECK (role IN ('admin','tutor')),
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ DEFAULT now()
);
CREATE TABLE IF NOT EXISTS user_branches (
user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
branch_id INT NOT NULL REFERENCES branches(id) ON DELETE CASCADE,
PRIMARY KEY (user_id, branch_id)
);
CREATE TABLE IF NOT EXISTS sessions (
id SERIAL PRIMARY KEY,
user_id INT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
token VARCHAR(64) NOT NULL UNIQUE,
created_at TIMESTAMPTZ DEFAULT now(),
expires_at TIMESTAMPTZ NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_sessions_token ON sessions(token);
CREATE INDEX IF NOT EXISTS idx_sessions_expires_at ON sessions(expires_at);
ALTER TABLE audit_log ADD COLUMN IF NOT EXISTS user_id INT REFERENCES users(id) ON DELETE SET NULL;
CREATE TABLE IF NOT EXISTS group_photos (
id SERIAL PRIMARY KEY,
group_id INT NOT NULL REFERENCES groups(id) ON DELETE CASCADE,
photo_path VARCHAR(255) NOT NULL,
caption TEXT,
taken_at DATE,
created_at TIMESTAMPTZ DEFAULT now()
);
ALTER TABLE group_photos ADD COLUMN IF NOT EXISTS sort_order INT DEFAULT 0;
CREATE INDEX IF NOT EXISTS idx_group_photos_group_id ON group_photos(group_id);
UPDATE entries e SET photo_path = p.photo_path
FROM (
SELECT DISTINCT ON (entry_id) entry_id, photo_path
FROM entry_photos ORDER BY entry_id, sort_order, id
) p
WHERE e.photo_path IS NULL AND p.entry_id = e.id;