197 lines
8.4 KiB
MySQL
197 lines
8.4 KiB
MySQL
|
|
-- Supply domain schema (PostgreSQL 15)
|
||
|
|
-- Single executable DDL source for supply_* tables.
|
||
|
|
-- Updated: 2026-03-25
|
||
|
|
|
||
|
|
BEGIN;
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS supply_accounts (
|
||
|
|
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||
|
|
user_id BIGINT NOT NULL,
|
||
|
|
platform VARCHAR(50) NOT NULL,
|
||
|
|
account_type VARCHAR(20) NOT NULL CHECK (account_type IN ('api_key', 'oauth')),
|
||
|
|
account_name VARCHAR(100),
|
||
|
|
encrypted_credentials TEXT NOT NULL,
|
||
|
|
key_id VARCHAR(100),
|
||
|
|
status VARCHAR(20) NOT NULL DEFAULT 'pending'
|
||
|
|
CHECK (status IN ('pending', 'active', 'suspended', 'disabled')),
|
||
|
|
risk_level VARCHAR(20) NOT NULL DEFAULT 'normal'
|
||
|
|
CHECK (risk_level IN ('low', 'normal', 'high')),
|
||
|
|
total_quota NUMERIC(20, 6),
|
||
|
|
available_quota NUMERIC(20, 6),
|
||
|
|
frozen_quota NUMERIC(20, 6) DEFAULT 0,
|
||
|
|
is_verified BOOLEAN DEFAULT FALSE,
|
||
|
|
verified_at TIMESTAMPTZ,
|
||
|
|
last_check_at TIMESTAMPTZ,
|
||
|
|
tos_compliant BOOLEAN DEFAULT TRUE,
|
||
|
|
tos_check_result TEXT,
|
||
|
|
total_requests BIGINT DEFAULT 0,
|
||
|
|
total_tokens BIGINT DEFAULT 0,
|
||
|
|
total_cost NUMERIC(20, 6) DEFAULT 0,
|
||
|
|
success_rate NUMERIC(5, 2) DEFAULT 0,
|
||
|
|
risk_score INT DEFAULT 0,
|
||
|
|
risk_reason TEXT,
|
||
|
|
is_frozen BOOLEAN DEFAULT FALSE,
|
||
|
|
frozen_reason TEXT,
|
||
|
|
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
created_by BIGINT,
|
||
|
|
updated_by BIGINT
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_supply_accounts_user_id ON supply_accounts (user_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_supply_accounts_platform ON supply_accounts (platform);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_supply_accounts_status ON supply_accounts (status);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_supply_accounts_risk_level ON supply_accounts (risk_level);
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS supply_packages (
|
||
|
|
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||
|
|
supply_account_id BIGINT NOT NULL REFERENCES supply_accounts(id),
|
||
|
|
user_id BIGINT NOT NULL,
|
||
|
|
platform VARCHAR(50) NOT NULL,
|
||
|
|
model VARCHAR(100) NOT NULL,
|
||
|
|
total_quota NUMERIC(20, 6) NOT NULL,
|
||
|
|
available_quota NUMERIC(20, 6) NOT NULL,
|
||
|
|
sold_quota NUMERIC(20, 6) DEFAULT 0,
|
||
|
|
reserved_quota NUMERIC(20, 6) DEFAULT 0,
|
||
|
|
price_per_1m_input NUMERIC(20, 6),
|
||
|
|
price_per_1m_output NUMERIC(20, 6),
|
||
|
|
min_purchase NUMERIC(20, 6),
|
||
|
|
start_at TIMESTAMPTZ,
|
||
|
|
end_at TIMESTAMPTZ,
|
||
|
|
valid_days INT,
|
||
|
|
status VARCHAR(20) NOT NULL DEFAULT 'draft'
|
||
|
|
CHECK (status IN ('draft', 'active', 'paused', 'sold_out', 'expired')),
|
||
|
|
max_concurrent INT DEFAULT 10,
|
||
|
|
rate_limit_rpm INT DEFAULT 60,
|
||
|
|
total_orders INT DEFAULT 0,
|
||
|
|
total_revenue NUMERIC(20, 6) DEFAULT 0,
|
||
|
|
rating NUMERIC(3, 2) DEFAULT 0,
|
||
|
|
rating_count INT DEFAULT 0,
|
||
|
|
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_supply_packages_supply_account_id ON supply_packages (supply_account_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_supply_packages_user_id ON supply_packages (user_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_supply_packages_platform_model ON supply_packages (platform, model);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_supply_packages_status ON supply_packages (status);
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS supply_orders (
|
||
|
|
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||
|
|
order_no VARCHAR(64) NOT NULL UNIQUE,
|
||
|
|
buyer_user_id BIGINT NOT NULL,
|
||
|
|
buyer_team_id BIGINT,
|
||
|
|
supply_account_id BIGINT NOT NULL REFERENCES supply_accounts(id),
|
||
|
|
supplier_user_id BIGINT NOT NULL,
|
||
|
|
supply_package_id BIGINT NOT NULL REFERENCES supply_packages(id),
|
||
|
|
platform VARCHAR(50) NOT NULL,
|
||
|
|
model VARCHAR(100) NOT NULL,
|
||
|
|
quota_amount NUMERIC(20, 6) NOT NULL,
|
||
|
|
quota_tokens BIGINT,
|
||
|
|
unit_price NUMERIC(20, 6) NOT NULL,
|
||
|
|
total_amount NUMERIC(20, 6) NOT NULL,
|
||
|
|
platform_fee NUMERIC(20, 6) NOT NULL,
|
||
|
|
supplier_earnings NUMERIC(20, 6) NOT NULL,
|
||
|
|
status VARCHAR(20) NOT NULL DEFAULT 'pending'
|
||
|
|
CHECK (status IN ('pending', 'paid', 'using', 'expired', 'refunded')),
|
||
|
|
used_quota NUMERIC(20, 6) DEFAULT 0,
|
||
|
|
remaining_quota NUMERIC(20, 6),
|
||
|
|
expired_at TIMESTAMPTZ,
|
||
|
|
payment_method VARCHAR(20),
|
||
|
|
paid_at TIMESTAMPTZ,
|
||
|
|
payment_transaction_id VARCHAR(100),
|
||
|
|
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_supply_orders_buyer_user_id ON supply_orders (buyer_user_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_supply_orders_supplier_user_id ON supply_orders (supplier_user_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_supply_orders_supply_package_id ON supply_orders (supply_package_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_supply_orders_status ON supply_orders (status);
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS supply_usage_records (
|
||
|
|
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||
|
|
order_id BIGINT NOT NULL REFERENCES supply_orders(id),
|
||
|
|
buyer_user_id BIGINT NOT NULL,
|
||
|
|
supply_account_id BIGINT NOT NULL REFERENCES supply_accounts(id),
|
||
|
|
supplier_user_id BIGINT NOT NULL,
|
||
|
|
request_id VARCHAR(64) NOT NULL,
|
||
|
|
upstream_request_id VARCHAR(128),
|
||
|
|
api_key_id BIGINT,
|
||
|
|
platform VARCHAR(50) NOT NULL,
|
||
|
|
model VARCHAR(100) NOT NULL,
|
||
|
|
endpoint VARCHAR(100) NOT NULL,
|
||
|
|
request_tokens BIGINT,
|
||
|
|
response_tokens BIGINT,
|
||
|
|
total_tokens BIGINT GENERATED ALWAYS AS (COALESCE(request_tokens, 0) + COALESCE(response_tokens, 0)) STORED,
|
||
|
|
input_cost NUMERIC(20, 6),
|
||
|
|
output_cost NUMERIC(20, 6),
|
||
|
|
total_cost NUMERIC(20, 6) NOT NULL,
|
||
|
|
unit_price NUMERIC(20, 6) NOT NULL,
|
||
|
|
response_status INT,
|
||
|
|
latency_ms INT,
|
||
|
|
error_message TEXT,
|
||
|
|
success BOOLEAN DEFAULT TRUE,
|
||
|
|
started_at TIMESTAMPTZ NOT NULL,
|
||
|
|
completed_at TIMESTAMPTZ,
|
||
|
|
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_supply_usage_records_request_id ON supply_usage_records (request_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_supply_usage_records_order_id ON supply_usage_records (order_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_supply_usage_records_supply_account_id ON supply_usage_records (supply_account_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_supply_usage_records_platform_model ON supply_usage_records (platform, model);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_supply_usage_records_started_at ON supply_usage_records (started_at);
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS supply_earnings (
|
||
|
|
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||
|
|
user_id BIGINT NOT NULL,
|
||
|
|
supply_account_id BIGINT REFERENCES supply_accounts(id),
|
||
|
|
order_id BIGINT REFERENCES supply_orders(id),
|
||
|
|
usage_record_id BIGINT REFERENCES supply_usage_records(id),
|
||
|
|
earnings_type VARCHAR(20) NOT NULL CHECK (earnings_type IN ('usage', 'bonus', 'refund')),
|
||
|
|
amount NUMERIC(20, 6) NOT NULL,
|
||
|
|
currency VARCHAR(10) DEFAULT 'CNY',
|
||
|
|
status VARCHAR(20) NOT NULL DEFAULT 'pending'
|
||
|
|
CHECK (status IN ('pending', 'available', 'withdrawn', 'frozen')),
|
||
|
|
available_amount NUMERIC(20, 6) DEFAULT 0,
|
||
|
|
frozen_amount NUMERIC(20, 6) DEFAULT 0,
|
||
|
|
withdrawn_amount NUMERIC(20, 6) DEFAULT 0,
|
||
|
|
description TEXT,
|
||
|
|
earned_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
available_at TIMESTAMPTZ,
|
||
|
|
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_supply_earnings_user_id ON supply_earnings (user_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_supply_earnings_status ON supply_earnings (status);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_supply_earnings_earned_at ON supply_earnings (earned_at);
|
||
|
|
|
||
|
|
CREATE TABLE IF NOT EXISTS supply_settlements (
|
||
|
|
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
|
||
|
|
settlement_no VARCHAR(64) NOT NULL UNIQUE,
|
||
|
|
user_id BIGINT NOT NULL,
|
||
|
|
total_amount NUMERIC(20, 6) NOT NULL,
|
||
|
|
fee_amount NUMERIC(20, 6) DEFAULT 0,
|
||
|
|
net_amount NUMERIC(20, 6) NOT NULL,
|
||
|
|
status VARCHAR(20) NOT NULL DEFAULT 'pending'
|
||
|
|
CHECK (status IN ('pending', 'processing', 'completed', 'failed')),
|
||
|
|
payment_method VARCHAR(20),
|
||
|
|
payment_account VARCHAR(100),
|
||
|
|
payment_transaction_id VARCHAR(100),
|
||
|
|
paid_at TIMESTAMPTZ,
|
||
|
|
period_start DATE NOT NULL,
|
||
|
|
period_end DATE NOT NULL,
|
||
|
|
total_orders INT DEFAULT 0,
|
||
|
|
total_usage_records INT DEFAULT 0,
|
||
|
|
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
|
||
|
|
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
|
||
|
|
);
|
||
|
|
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_supply_settlements_user_id ON supply_settlements (user_id);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_supply_settlements_status ON supply_settlements (status);
|
||
|
|
CREATE INDEX IF NOT EXISTS idx_supply_settlements_period ON supply_settlements (period_start, period_end);
|
||
|
|
|
||
|
|
COMMIT;
|