Files
MyClub/database/migrations/20251102000001_create_engagement_system.up.sql
T
Tomas Dvorak 087f30e82c dev day #80
2025-11-02 21:31:00 +01:00

123 lines
5.4 KiB
SQL

-- Create user profiles table for gamification
CREATE TABLE IF NOT EXISTS user_profiles (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
user_id BIGINT NOT NULL UNIQUE,
points BIGINT NOT NULL DEFAULT 0,
level INTEGER NOT NULL DEFAULT 1,
xp BIGINT NOT NULL DEFAULT 0,
username VARCHAR(32) UNIQUE NOT NULL,
avatar_url VARCHAR(500),
animated_avatar_url VARCHAR(500),
avatar_upload_unlocked BOOLEAN NOT NULL DEFAULT FALSE,
CONSTRAINT fk_user_profiles_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
CREATE INDEX idx_user_profiles_user_id ON user_profiles(user_id);
CREATE INDEX idx_user_profiles_points ON user_profiles(points DESC);
CREATE INDEX idx_user_profiles_level ON user_profiles(level DESC);
CREATE INDEX idx_user_profiles_xp ON user_profiles(xp DESC);
CREATE INDEX idx_user_profiles_username ON user_profiles(LOWER(username));
-- Create points transactions log
CREATE TABLE IF NOT EXISTS points_transactions (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
user_id BIGINT NOT NULL,
delta BIGINT NOT NULL,
xp_delta BIGINT NOT NULL DEFAULT 0,
reason VARCHAR(64) NOT NULL,
meta JSONB,
CONSTRAINT fk_points_tx_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
CREATE INDEX idx_points_tx_user ON points_transactions(user_id, created_at DESC);
CREATE INDEX idx_points_tx_reason ON points_transactions(reason);
CREATE INDEX idx_points_tx_created ON points_transactions(created_at DESC);
-- Create achievements table
CREATE TABLE IF NOT EXISTS achievements (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
code VARCHAR(64) UNIQUE NOT NULL,
title VARCHAR(255) NOT NULL,
description TEXT,
points BIGINT NOT NULL DEFAULT 0,
xp BIGINT NOT NULL DEFAULT 0,
icon VARCHAR(255),
active BOOLEAN NOT NULL DEFAULT TRUE
);
CREATE INDEX idx_achievements_code ON achievements(code);
CREATE INDEX idx_achievements_active ON achievements(active);
-- Create user achievements junction table
CREATE TABLE IF NOT EXISTS user_achievements (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
user_id BIGINT NOT NULL,
achievement_id BIGINT NOT NULL,
CONSTRAINT fk_user_ach_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
CONSTRAINT fk_user_ach_achievement FOREIGN KEY (achievement_id) REFERENCES achievements(id) ON DELETE CASCADE,
UNIQUE (user_id, achievement_id)
);
CREATE INDEX idx_user_ach_user ON user_achievements(user_id);
CREATE INDEX idx_user_ach_achievement ON user_achievements(achievement_id);
-- Create reward items table
CREATE TABLE IF NOT EXISTS reward_items (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
name VARCHAR(255) NOT NULL,
type VARCHAR(32) NOT NULL,
cost_points BIGINT NOT NULL,
image_url VARCHAR(500),
stock INTEGER NOT NULL DEFAULT 0,
active BOOLEAN NOT NULL DEFAULT TRUE,
metadata JSONB
);
CREATE INDEX idx_reward_items_type ON reward_items(type);
CREATE INDEX idx_reward_items_active ON reward_items(active);
CREATE INDEX idx_reward_items_cost ON reward_items(cost_points);
-- Create reward redemptions table
CREATE TABLE IF NOT EXISTS reward_redemptions (
id BIGSERIAL PRIMARY KEY,
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
user_id BIGINT NOT NULL,
reward_id BIGINT NOT NULL,
status VARCHAR(24) NOT NULL DEFAULT 'pending',
CONSTRAINT fk_reward_red_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE,
CONSTRAINT fk_reward_red_reward FOREIGN KEY (reward_id) REFERENCES reward_items(id) ON DELETE CASCADE
);
CREATE INDEX idx_reward_red_user ON reward_redemptions(user_id);
CREATE INDEX idx_reward_red_reward ON reward_redemptions(reward_id);
CREATE INDEX idx_reward_red_status ON reward_redemptions(status);
CREATE INDEX idx_reward_red_created ON reward_redemptions(created_at DESC);
-- Insert default achievements
INSERT INTO achievements (code, title, description, points, xp, active) VALUES
('first_comment', 'První komentář', 'Napsal/a jste první komentář.', 10, 10, TRUE),
('first_vote', 'První hlasování', 'Poprvé jste hlasoval/a v anketě.', 8, 8, TRUE),
('newsletter_sub', 'Odběr novinek', 'Přihlášení k odběru newsletteru.', 12, 12, TRUE),
('comments_10', 'Komentátor', '10 komentářů!', 20, 20, TRUE),
('votes_10', 'Hlasující', '10 hlasování!', 20, 20, TRUE),
('comments_50', 'Aktivní člen', '50 komentářů!', 50, 50, TRUE),
('votes_50', 'Věrný fanoušek', '50 hlasování!', 50, 50, TRUE),
('comments_100', 'Veterán diskuzí', '100 komentářů!', 100, 100, TRUE)
ON CONFLICT (code) DO NOTHING;
-- Create default avatar upload unlock reward
INSERT INTO reward_items (name, type, cost_points, stock, active) VALUES
('Odemknout vlastní avatar (upload)', 'avatar_upload_unlock', 100, -1, TRUE)
ON CONFLICT DO NOTHING;