feat: implement new structure
This commit is contained in:
298
backend/database/migrations/20251227120000_add_api_support.sql
Normal file
298
backend/database/migrations/20251227120000_add_api_support.sql
Normal file
@@ -0,0 +1,298 @@
|
||||
-- +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
|
||||
Reference in New Issue
Block a user