Files
quyun-v2/backend/database/migrations/20251227120000_add_api_support.sql
2025-12-29 09:30:49 +08:00

298 lines
9.6 KiB
SQL

-- +goose Up
-- Users
CREATE TABLE IF NOT EXISTS users (
id BIGSERIAL PRIMARY KEY,
username VARCHAR(255) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
roles TEXT[] DEFAULT '{user}',
status VARCHAR(50) DEFAULT 'active',
metas JSONB DEFAULT '{}',
balance BIGINT DEFAULT 0,
balance_frozen BIGINT DEFAULT 0,
verified_at TIMESTAMP WITH TIME ZONE,
-- New fields
nickname VARCHAR(255) DEFAULT '',
avatar VARCHAR(512) DEFAULT '',
gender VARCHAR(32) DEFAULT 'secret',
bio VARCHAR(512) DEFAULT '',
birthday DATE,
location JSONB DEFAULT '{}',
points BIGINT DEFAULT 0,
phone VARCHAR(32) DEFAULT '',
is_real_name_verified BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE
);
-- Tenants
CREATE TABLE IF NOT EXISTS tenants (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL,
code VARCHAR(64) NOT NULL UNIQUE,
uuid UUID NOT NULL,
name VARCHAR(128) NOT NULL,
status VARCHAR(64) NOT NULL,
config JSONB DEFAULT '{}',
expired_at TIMESTAMP WITH TIME ZONE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_tenants_user_id ON tenants(user_id);
-- TenantUsers
CREATE TABLE IF NOT EXISTS tenant_users (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
role TEXT[] DEFAULT '{member}',
status VARCHAR(50) DEFAULT 'verified',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
UNIQUE(tenant_id, user_id)
);
-- Contents
CREATE TABLE IF NOT EXISTS contents (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
title VARCHAR(255) NOT NULL,
description TEXT NOT NULL,
status VARCHAR(32) DEFAULT 'draft',
visibility VARCHAR(32) DEFAULT 'tenant_only',
preview_seconds INT DEFAULT 60,
preview_downloadable BOOLEAN DEFAULT FALSE,
published_at TIMESTAMP WITH TIME ZONE,
summary VARCHAR(256) DEFAULT '',
tags JSONB DEFAULT '[]',
-- New fields
body TEXT DEFAULT '',
genre VARCHAR(64) DEFAULT '',
views INT DEFAULT 0,
likes INT DEFAULT 0,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE
);
CREATE INDEX IF NOT EXISTS idx_contents_tenant_id ON contents(tenant_id);
-- MediaAssets
CREATE TABLE IF NOT EXISTS media_assets (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
type VARCHAR(32) DEFAULT 'video',
status VARCHAR(32) DEFAULT 'uploaded',
provider VARCHAR(64) NOT NULL,
bucket VARCHAR(128) NOT NULL,
object_key VARCHAR(512) NOT NULL,
meta JSONB DEFAULT '{}',
variant VARCHAR(32) DEFAULT 'main',
source_asset_id BIGINT DEFAULT 0,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE
);
-- ContentAssets
CREATE TABLE IF NOT EXISTS content_assets (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
content_id BIGINT NOT NULL,
asset_id BIGINT NOT NULL,
role VARCHAR(32) DEFAULT 'main',
sort INT DEFAULT 0,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- ContentPrices
CREATE TABLE IF NOT EXISTS content_prices (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
content_id BIGINT NOT NULL,
currency VARCHAR(16) DEFAULT 'CNY',
price_amount BIGINT NOT NULL,
discount_type VARCHAR(16) DEFAULT 'none',
discount_value BIGINT DEFAULT 0,
discount_start_at TIMESTAMP WITH TIME ZONE,
discount_end_at TIMESTAMP WITH TIME ZONE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
UNIQUE(tenant_id, content_id)
);
-- ContentAccess
CREATE TABLE IF NOT EXISTS content_access (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
content_id BIGINT NOT NULL,
order_id BIGINT DEFAULT 0,
status VARCHAR(16) DEFAULT 'active',
revoked_at TIMESTAMP WITH TIME ZONE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
UNIQUE(tenant_id, user_id, content_id)
);
-- Orders
CREATE TABLE IF NOT EXISTS orders (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
type VARCHAR(32) DEFAULT 'content_purchase',
status VARCHAR(32) DEFAULT 'created',
currency VARCHAR(16) DEFAULT 'CNY',
amount_original BIGINT NOT NULL,
amount_discount BIGINT NOT NULL,
amount_paid BIGINT NOT NULL,
snapshot JSONB DEFAULT '{}',
idempotency_key VARCHAR(128) NOT NULL,
paid_at TIMESTAMP WITH TIME ZONE,
refunded_at TIMESTAMP WITH TIME ZONE,
refund_forced BOOLEAN DEFAULT FALSE,
refund_operator_user_id BIGINT DEFAULT 0,
refund_reason VARCHAR(255) DEFAULT '',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- OrderItems
CREATE TABLE IF NOT EXISTS order_items (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
order_id BIGINT NOT NULL,
content_id BIGINT NOT NULL,
content_user_id BIGINT NOT NULL,
amount_paid BIGINT NOT NULL,
snapshot JSONB DEFAULT '{}',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- TenantLedgers
CREATE TABLE IF NOT EXISTS tenant_ledgers (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
order_id BIGINT DEFAULT 0,
type VARCHAR(32) NOT NULL,
amount BIGINT NOT NULL,
balance_before BIGINT NOT NULL,
balance_after BIGINT NOT NULL,
frozen_before BIGINT NOT NULL,
frozen_after BIGINT NOT NULL,
idempotency_key VARCHAR(128) NOT NULL,
remark VARCHAR(255) NOT NULL,
operator_user_id BIGINT DEFAULT 0,
biz_ref_type VARCHAR(32) DEFAULT '',
biz_ref_id BIGINT DEFAULT 0,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- TenantInvites
CREATE TABLE IF NOT EXISTS tenant_invites (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
code VARCHAR(64) NOT NULL,
status VARCHAR(32) DEFAULT 'active',
max_uses INT NOT NULL,
used_count INT DEFAULT 0,
expires_at TIMESTAMP WITH TIME ZONE,
disabled_at TIMESTAMP WITH TIME ZONE,
disabled_operator_user_id BIGINT DEFAULT 0,
remark VARCHAR(255) DEFAULT '',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- TenantJoinRequests
CREATE TABLE IF NOT EXISTS tenant_join_requests (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
status VARCHAR(32) DEFAULT 'pending',
reason VARCHAR(255) NOT NULL,
decided_at TIMESTAMP WITH TIME ZONE,
decided_operator_user_id BIGINT DEFAULT 0,
decided_reason VARCHAR(255) DEFAULT '',
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
-- Comments
CREATE TABLE IF NOT EXISTS comments (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
content_id BIGINT NOT NULL,
reply_to BIGINT DEFAULT 0,
content TEXT NOT NULL,
likes INT DEFAULT 0,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
deleted_at TIMESTAMP WITH TIME ZONE
);
CREATE INDEX IF NOT EXISTS idx_comments_content_id ON comments(content_id);
CREATE INDEX IF NOT EXISTS idx_comments_user_id ON comments(user_id);
-- User Content Actions (Like, Favorite)
CREATE TABLE IF NOT EXISTS user_content_actions (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL,
content_id BIGINT NOT NULL,
type VARCHAR(32) NOT NULL, -- like, favorite
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
UNIQUE(user_id, content_id, type)
);
-- User Comment Actions (Like)
CREATE TABLE IF NOT EXISTS user_comment_actions (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL,
comment_id BIGINT NOT NULL,
type VARCHAR(32) NOT NULL, -- like
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
UNIQUE(user_id, comment_id, type)
);
-- Payout Accounts
CREATE TABLE IF NOT EXISTS payout_accounts (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL, -- Associated with a creator tenant
user_id BIGINT NOT NULL, -- Creator user
type VARCHAR(32) NOT NULL, -- bank, alipay
name VARCHAR(128) NOT NULL,
account VARCHAR(128) NOT NULL,
realname VARCHAR(128) NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_payout_accounts_tenant_id ON payout_accounts(tenant_id);
-- Notifications
CREATE TABLE IF NOT EXISTS notifications (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL,
tenant_id BIGINT DEFAULT 0, -- Optional source tenant
type VARCHAR(32) NOT NULL, -- system, order, audit, interaction
title VARCHAR(255) NOT NULL,
content TEXT NOT NULL,
is_read BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE INDEX IF NOT EXISTS idx_notifications_user_id ON notifications(user_id);
-- +goose Down
-- Revert logic omitted for dev speed in this context