298 lines
9.6 KiB
SQL
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 |