597 lines
20 KiB
SQL
597 lines
20 KiB
SQL
-- AlphaX Agent | Crypto PostgreSQL initial schema.
|
||
-- Keep column names compatible with the current SQLite data model.
|
||
|
||
CREATE TABLE IF NOT EXISTS schema_migrations (
|
||
version TEXT PRIMARY KEY,
|
||
applied_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS coin_state (
|
||
symbol TEXT PRIMARY KEY,
|
||
state TEXT NOT NULL DEFAULT '蓄力',
|
||
score INTEGER DEFAULT 0,
|
||
anomaly_type TEXT DEFAULT '',
|
||
sector TEXT DEFAULT '',
|
||
leader_status TEXT DEFAULT '',
|
||
detected_at TEXT NOT NULL,
|
||
last_alert_time TEXT DEFAULT '',
|
||
last_alert_level TEXT DEFAULT '',
|
||
detail_json TEXT DEFAULT '{}'
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS screening_log (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
scan_time TEXT NOT NULL,
|
||
layer TEXT NOT NULL,
|
||
symbol TEXT NOT NULL,
|
||
state TEXT NOT NULL,
|
||
score INTEGER DEFAULT 0,
|
||
price DOUBLE PRECISION NOT NULL,
|
||
signals TEXT DEFAULT '',
|
||
sector TEXT DEFAULT '',
|
||
leader_status TEXT DEFAULT '',
|
||
is_meme INTEGER DEFAULT 0,
|
||
change_24h DOUBLE PRECISION DEFAULT 0,
|
||
funding_rate DOUBLE PRECISION DEFAULT 0,
|
||
detail_json TEXT DEFAULT '{}'
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_screening_log_time ON screening_log(scan_time DESC);
|
||
CREATE INDEX IF NOT EXISTS idx_screening_log_layer_time ON screening_log(layer, scan_time DESC);
|
||
CREATE INDEX IF NOT EXISTS idx_screening_log_symbol_time ON screening_log(symbol, scan_time DESC);
|
||
|
||
CREATE TABLE IF NOT EXISTS recommendation (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
symbol TEXT NOT NULL,
|
||
rec_time TEXT NOT NULL,
|
||
rec_state TEXT NOT NULL,
|
||
rec_score INTEGER DEFAULT 0,
|
||
entry_price DOUBLE PRECISION NOT NULL,
|
||
stop_loss DOUBLE PRECISION DEFAULT 0,
|
||
tp1 DOUBLE PRECISION DEFAULT 0,
|
||
tp2 DOUBLE PRECISION DEFAULT 0,
|
||
sector TEXT DEFAULT '',
|
||
signals TEXT DEFAULT '',
|
||
is_meme INTEGER DEFAULT 0,
|
||
status TEXT DEFAULT 'active',
|
||
current_price DOUBLE PRECISION DEFAULT 0,
|
||
max_price DOUBLE PRECISION DEFAULT 0,
|
||
min_price DOUBLE PRECISION DEFAULT 0,
|
||
pnl_pct DOUBLE PRECISION DEFAULT 0,
|
||
max_pnl_pct DOUBLE PRECISION DEFAULT 0,
|
||
max_drawdown_pct DOUBLE PRECISION DEFAULT 0,
|
||
hit_tp1_time TEXT DEFAULT '',
|
||
hit_tp2_time TEXT DEFAULT '',
|
||
stopped_out_time TEXT DEFAULT '',
|
||
expired_time TEXT DEFAULT '',
|
||
last_track_time TEXT DEFAULT '',
|
||
entry_plan_json TEXT DEFAULT '{}',
|
||
action_status TEXT DEFAULT '持有',
|
||
strategy_version TEXT DEFAULT '',
|
||
direction TEXT DEFAULT '中性',
|
||
force_reason TEXT DEFAULT '',
|
||
base_state TEXT DEFAULT '',
|
||
sector_signal_count INTEGER DEFAULT 0,
|
||
market_context_json TEXT DEFAULT '{}',
|
||
derivatives_context_json TEXT DEFAULT '{}',
|
||
sector_context_json TEXT DEFAULT '{}',
|
||
lifecycle_state TEXT DEFAULT 'watching',
|
||
display_bucket TEXT DEFAULT 'watch_pool',
|
||
execution_status TEXT DEFAULT 'observe',
|
||
state_reason TEXT DEFAULT '',
|
||
entry_triggered INTEGER DEFAULT 0,
|
||
archived_at TEXT DEFAULT '',
|
||
signal_codes_json TEXT DEFAULT '[]',
|
||
signal_labels_json TEXT DEFAULT '[]',
|
||
opportunity_level TEXT DEFAULT '',
|
||
opportunity_level_label TEXT DEFAULT '',
|
||
holding_horizon TEXT DEFAULT '',
|
||
entry_model TEXT DEFAULT '',
|
||
stop_model TEXT DEFAULT '',
|
||
tp_model TEXT DEFAULT ''
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_rec_active_symbol_bucket ON recommendation(symbol, status, display_bucket, id DESC);
|
||
CREATE INDEX IF NOT EXISTS idx_rec_display_bucket_time ON recommendation(display_bucket, rec_time DESC);
|
||
CREATE INDEX IF NOT EXISTS idx_rec_symbol_time ON recommendation(symbol, rec_time DESC);
|
||
CREATE INDEX IF NOT EXISTS idx_rec_opportunity_level_time ON recommendation(opportunity_level, rec_time DESC);
|
||
|
||
CREATE TABLE IF NOT EXISTS price_tracking (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
rec_id BIGINT NOT NULL,
|
||
symbol TEXT NOT NULL,
|
||
track_time TEXT NOT NULL,
|
||
price DOUBLE PRECISION NOT NULL,
|
||
pnl_pct DOUBLE PRECISION DEFAULT 0
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_price_tracking_rec_id_id ON price_tracking(rec_id, id DESC);
|
||
CREATE INDEX IF NOT EXISTS idx_price_tracking_rec_time ON price_tracking(rec_id, track_time DESC);
|
||
|
||
CREATE TABLE IF NOT EXISTS latest_price_cache (
|
||
symbol TEXT PRIMARY KEY,
|
||
price DOUBLE PRECISION NOT NULL,
|
||
updated_at TEXT NOT NULL,
|
||
source TEXT DEFAULT 'tracker'
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_latest_price_cache_updated_at ON latest_price_cache(updated_at);
|
||
|
||
CREATE TABLE IF NOT EXISTS cron_run_log (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
job_name TEXT NOT NULL,
|
||
script_name TEXT NOT NULL,
|
||
run_status TEXT NOT NULL,
|
||
result_status TEXT DEFAULT '',
|
||
started_at TEXT NOT NULL,
|
||
finished_at TEXT NOT NULL,
|
||
duration_ms INTEGER DEFAULT 0,
|
||
summary_json TEXT DEFAULT '{}',
|
||
error_message TEXT DEFAULT ''
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_cron_run_log_job_started ON cron_run_log(job_name, started_at DESC);
|
||
|
||
CREATE TABLE IF NOT EXISTS signal_performance (
|
||
signal_type TEXT PRIMARY KEY,
|
||
category TEXT DEFAULT '',
|
||
total_count INTEGER DEFAULT 0,
|
||
hit_count INTEGER DEFAULT 0,
|
||
miss_count INTEGER DEFAULT 0,
|
||
hit_rate DOUBLE PRECISION DEFAULT 0,
|
||
avg_pnl DOUBLE PRECISION DEFAULT 0,
|
||
weight DOUBLE PRECISION DEFAULT 1.0,
|
||
last_updated TEXT DEFAULT ''
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS review_log (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
rec_id BIGINT NOT NULL,
|
||
symbol TEXT NOT NULL,
|
||
review_time TEXT NOT NULL,
|
||
outcome TEXT NOT NULL,
|
||
pnl_48h DOUBLE PRECISION DEFAULT 0,
|
||
max_pnl_48h DOUBLE PRECISION DEFAULT 0,
|
||
triggered_signals TEXT DEFAULT '',
|
||
hit_signals TEXT DEFAULT '',
|
||
miss_signals TEXT DEFAULT '',
|
||
lesson TEXT DEFAULT ''
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_review_log_rec_id ON review_log(rec_id);
|
||
CREATE INDEX IF NOT EXISTS idx_review_log_time ON review_log(review_time DESC);
|
||
|
||
CREATE TABLE IF NOT EXISTS missed_explosions (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
symbol TEXT NOT NULL,
|
||
detect_time TEXT NOT NULL,
|
||
price_at_detect DOUBLE PRECISION DEFAULT 0,
|
||
price_before DOUBLE PRECISION DEFAULT 0,
|
||
gain_pct DOUBLE PRECISION DEFAULT 0,
|
||
reason_missed TEXT DEFAULT '',
|
||
features_detected TEXT DEFAULT '',
|
||
lesson TEXT DEFAULT ''
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS strategy_iteration_log (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
run_date TEXT NOT NULL,
|
||
created_at TEXT NOT NULL,
|
||
trigger_source TEXT DEFAULT 'daily_review',
|
||
title TEXT NOT NULL,
|
||
summary TEXT DEFAULT '',
|
||
findings_json TEXT DEFAULT '[]',
|
||
problems_json TEXT DEFAULT '[]',
|
||
actions_json TEXT DEFAULT '[]',
|
||
changed_rules_json TEXT DEFAULT '[]',
|
||
metrics_json TEXT DEFAULT '{}',
|
||
related_symbols_json TEXT DEFAULT '[]',
|
||
config_diff_json TEXT DEFAULT '{}',
|
||
effect_summary_json TEXT DEFAULT '{}',
|
||
pollution_summary_json TEXT DEFAULT '{}',
|
||
strategy_version TEXT DEFAULT '',
|
||
version_change_summary TEXT DEFAULT '',
|
||
success_analysis_json TEXT DEFAULT '{}',
|
||
failure_analysis_json TEXT DEFAULT '{}',
|
||
candidate_rules_json TEXT DEFAULT '[]',
|
||
release_decision TEXT DEFAULT '',
|
||
release_reason TEXT DEFAULT '',
|
||
confidence_level TEXT DEFAULT '',
|
||
promotion_state TEXT DEFAULT 'research_only'
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS strategy_rule_candidate (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
created_at TEXT NOT NULL,
|
||
source TEXT DEFAULT '',
|
||
rule_type TEXT DEFAULT '',
|
||
signal_name TEXT DEFAULT '',
|
||
rule_description TEXT DEFAULT '',
|
||
support_count INTEGER DEFAULT 0,
|
||
success_count INTEGER DEFAULT 0,
|
||
fail_count INTEGER DEFAULT 0,
|
||
avg_pnl DOUBLE PRECISION DEFAULT 0,
|
||
max_gain DOUBLE PRECISION DEFAULT 0,
|
||
max_drawdown DOUBLE PRECISION DEFAULT 0,
|
||
confidence_score DOUBLE PRECISION DEFAULT 0,
|
||
sample_size INTEGER DEFAULT 0,
|
||
status TEXT DEFAULT 'candidate',
|
||
release_version TEXT DEFAULT '',
|
||
notes TEXT DEFAULT '',
|
||
source_ref TEXT DEFAULT ''
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_rule_candidate_status ON strategy_rule_candidate(status, created_at);
|
||
|
||
CREATE TABLE IF NOT EXISTS strategy_failure_pattern (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
created_at TEXT NOT NULL,
|
||
symbol TEXT NOT NULL,
|
||
version TEXT DEFAULT '',
|
||
failure_type TEXT DEFAULT '',
|
||
failure_reason TEXT DEFAULT '',
|
||
signal_combo TEXT DEFAULT '[]',
|
||
market_context_json TEXT DEFAULT '{}',
|
||
entry_quality_issue TEXT DEFAULT '',
|
||
pnl_pct DOUBLE PRECISION DEFAULT 0,
|
||
max_drawdown_pct DOUBLE PRECISION DEFAULT 0,
|
||
lesson TEXT DEFAULT ''
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_failure_pattern_type ON strategy_failure_pattern(failure_type, created_at);
|
||
|
||
CREATE TABLE IF NOT EXISTS push_log (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
symbol TEXT NOT NULL,
|
||
push_type TEXT NOT NULL,
|
||
action_status TEXT DEFAULT '',
|
||
pushed_at TEXT NOT NULL,
|
||
rec_id BIGINT DEFAULT 0
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_push_lookup ON push_log(symbol, push_type, pushed_at);
|
||
CREATE INDEX IF NOT EXISTS idx_push_log_rec_action ON push_log(rec_id, push_type, action_status, pushed_at);
|
||
|
||
CREATE TABLE IF NOT EXISTS sentiment_events (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
symbol TEXT NOT NULL,
|
||
name TEXT DEFAULT '',
|
||
source TEXT NOT NULL,
|
||
event_type TEXT NOT NULL,
|
||
trend_rank INTEGER DEFAULT 0,
|
||
trend_score INTEGER DEFAULT 0,
|
||
market_cap_rank INTEGER DEFAULT 0,
|
||
extra_json TEXT DEFAULT '{}',
|
||
detected_at TEXT NOT NULL
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_sentiment_lookup ON sentiment_events(symbol, source, detected_at);
|
||
|
||
CREATE TABLE IF NOT EXISTS llm_insights (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
target_type TEXT NOT NULL,
|
||
target_id TEXT NOT NULL,
|
||
insight_type TEXT NOT NULL,
|
||
prompt_version TEXT NOT NULL,
|
||
input_hash TEXT NOT NULL,
|
||
status TEXT NOT NULL DEFAULT 'success',
|
||
input_json TEXT DEFAULT '{}',
|
||
content_json TEXT DEFAULT '{}',
|
||
error TEXT DEFAULT '',
|
||
model TEXT DEFAULT '',
|
||
created_at TEXT NOT NULL,
|
||
updated_at TEXT NOT NULL
|
||
);
|
||
CREATE UNIQUE INDEX IF NOT EXISTS idx_llm_insights_unique
|
||
ON llm_insights(target_type, target_id, insight_type, input_hash);
|
||
CREATE INDEX IF NOT EXISTS idx_llm_insights_lookup
|
||
ON llm_insights(target_type, target_id, insight_type, status, updated_at);
|
||
|
||
CREATE TABLE IF NOT EXISTS event_news (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
event_hash TEXT UNIQUE,
|
||
source TEXT NOT NULL,
|
||
symbol TEXT NOT NULL,
|
||
title TEXT NOT NULL,
|
||
url TEXT DEFAULT '',
|
||
published_at TEXT NOT NULL,
|
||
detected_at TEXT NOT NULL,
|
||
importance TEXT DEFAULT 'B',
|
||
event_type TEXT DEFAULT '',
|
||
raw_json TEXT DEFAULT '{}',
|
||
processed INTEGER DEFAULT 0,
|
||
decision TEXT DEFAULT '',
|
||
tech_score INTEGER DEFAULT 0,
|
||
rec_id BIGINT DEFAULT 0,
|
||
pushed INTEGER DEFAULT 0
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_event_news_time ON event_news(published_at, detected_at);
|
||
CREATE INDEX IF NOT EXISTS idx_event_news_symbol ON event_news(symbol);
|
||
|
||
CREATE TABLE IF NOT EXISTS onchain_token_map (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
symbol TEXT NOT NULL,
|
||
chain TEXT NOT NULL,
|
||
contract_address TEXT NOT NULL,
|
||
source TEXT DEFAULT '',
|
||
confidence INTEGER DEFAULT 0,
|
||
is_active INTEGER DEFAULT 1,
|
||
raw_json TEXT DEFAULT '{}',
|
||
created_at TEXT NOT NULL,
|
||
updated_at TEXT NOT NULL,
|
||
UNIQUE(symbol, chain, contract_address)
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_onchain_token_map_symbol ON onchain_token_map(symbol, confidence, is_active);
|
||
|
||
CREATE TABLE IF NOT EXISTS onchain_events (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
event_hash TEXT UNIQUE,
|
||
chain TEXT NOT NULL,
|
||
symbol TEXT NOT NULL,
|
||
contract_address TEXT DEFAULT '',
|
||
event_type TEXT NOT NULL,
|
||
signal_code TEXT NOT NULL,
|
||
signal_label TEXT DEFAULT '',
|
||
direction TEXT DEFAULT 'neutral',
|
||
value_usd DOUBLE PRECISION DEFAULT 0,
|
||
amount DOUBLE PRECISION DEFAULT 0,
|
||
tx_hash TEXT DEFAULT '',
|
||
wallet_address TEXT DEFAULT '',
|
||
wallet_label TEXT DEFAULT '',
|
||
counterparty_label TEXT DEFAULT '',
|
||
confidence INTEGER DEFAULT 0,
|
||
severity TEXT DEFAULT 'B',
|
||
status TEXT DEFAULT 'new',
|
||
detected_at TEXT NOT NULL,
|
||
source TEXT DEFAULT '',
|
||
url TEXT DEFAULT '',
|
||
raw_json TEXT DEFAULT '{}'
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_onchain_events_time ON onchain_events(detected_at, signal_code);
|
||
CREATE INDEX IF NOT EXISTS idx_onchain_events_symbol ON onchain_events(symbol, detected_at);
|
||
CREATE INDEX IF NOT EXISTS idx_onchain_events_chain ON onchain_events(chain, detected_at);
|
||
|
||
CREATE TABLE IF NOT EXISTS onchain_token_metrics (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
symbol TEXT NOT NULL,
|
||
chain TEXT NOT NULL,
|
||
contract_address TEXT DEFAULT '',
|
||
"window" TEXT NOT NULL,
|
||
metric_time TEXT NOT NULL,
|
||
dex_volume_usd DOUBLE PRECISION DEFAULT 0,
|
||
dex_volume_change_pct DOUBLE PRECISION DEFAULT 0,
|
||
liquidity_usd DOUBLE PRECISION DEFAULT 0,
|
||
liquidity_change_pct DOUBLE PRECISION DEFAULT 0,
|
||
exchange_netflow_usd DOUBLE PRECISION DEFAULT 0,
|
||
whale_accumulation_usd DOUBLE PRECISION DEFAULT 0,
|
||
holder_delta DOUBLE PRECISION DEFAULT 0,
|
||
smart_money_score DOUBLE PRECISION DEFAULT 0,
|
||
onchain_score DOUBLE PRECISION DEFAULT 0,
|
||
risk_score DOUBLE PRECISION DEFAULT 0,
|
||
source TEXT DEFAULT '',
|
||
raw_json TEXT DEFAULT '{}',
|
||
UNIQUE(symbol, chain, contract_address, "window", metric_time)
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_onchain_metrics_symbol ON onchain_token_metrics(symbol, metric_time);
|
||
|
||
CREATE TABLE IF NOT EXISTS onchain_raw_events (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
event_hash TEXT UNIQUE,
|
||
source TEXT NOT NULL,
|
||
chain TEXT NOT NULL,
|
||
event_type TEXT NOT NULL,
|
||
token_address TEXT DEFAULT '',
|
||
symbol_guess TEXT DEFAULT '',
|
||
name TEXT DEFAULT '',
|
||
title TEXT DEFAULT '',
|
||
description TEXT DEFAULT '',
|
||
url TEXT DEFAULT '',
|
||
icon TEXT DEFAULT '',
|
||
amount DOUBLE PRECISION DEFAULT 0,
|
||
total_amount DOUBLE PRECISION DEFAULT 0,
|
||
importance DOUBLE PRECISION DEFAULT 0,
|
||
mapped_symbol TEXT DEFAULT '',
|
||
mapping_status TEXT DEFAULT 'unmapped',
|
||
detected_at TEXT NOT NULL,
|
||
raw_json TEXT DEFAULT '{}'
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_onchain_raw_events_time ON onchain_raw_events(detected_at, importance);
|
||
CREATE INDEX IF NOT EXISTS idx_onchain_raw_events_chain ON onchain_raw_events(chain, detected_at);
|
||
CREATE INDEX IF NOT EXISTS idx_onchain_raw_events_mapping ON onchain_raw_events(mapping_status, detected_at);
|
||
|
||
CREATE TABLE IF NOT EXISTS app_user (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
email TEXT NOT NULL UNIQUE,
|
||
password_hash TEXT NOT NULL,
|
||
password_salt TEXT NOT NULL,
|
||
email_verified INTEGER DEFAULT 0,
|
||
status TEXT DEFAULT 'pending_email_verification',
|
||
invite_code TEXT NOT NULL UNIQUE,
|
||
invited_by_user_id BIGINT,
|
||
free_trial_claimed INTEGER DEFAULT 0,
|
||
created_at TEXT NOT NULL,
|
||
updated_at TEXT NOT NULL,
|
||
last_login_at TEXT DEFAULT '',
|
||
is_admin INTEGER DEFAULT 0
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_app_user_email ON app_user(email);
|
||
CREATE INDEX IF NOT EXISTS idx_app_user_invite_code ON app_user(invite_code);
|
||
|
||
CREATE TABLE IF NOT EXISTS email_verification_code (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
user_id BIGINT NOT NULL,
|
||
email TEXT NOT NULL,
|
||
code_hash TEXT NOT NULL,
|
||
purpose TEXT NOT NULL DEFAULT 'register',
|
||
expires_at TEXT NOT NULL,
|
||
used_at TEXT DEFAULT '',
|
||
created_at TEXT NOT NULL
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_email_code_lookup ON email_verification_code(email, purpose, used_at);
|
||
|
||
CREATE TABLE IF NOT EXISTS user_session (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
user_id BIGINT NOT NULL,
|
||
token_hash TEXT NOT NULL UNIQUE,
|
||
created_at TEXT NOT NULL,
|
||
expires_at TEXT NOT NULL,
|
||
revoked_at TEXT DEFAULT ''
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_user_session_token ON user_session(token_hash);
|
||
|
||
CREATE TABLE IF NOT EXISTS subscription_plan (
|
||
code TEXT PRIMARY KEY,
|
||
name TEXT NOT NULL,
|
||
duration_days INTEGER NOT NULL,
|
||
price_usdt DOUBLE PRECISION DEFAULT 0,
|
||
status TEXT DEFAULT 'active',
|
||
sort_order INTEGER DEFAULT 0,
|
||
created_at TEXT NOT NULL
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS user_subscription (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
user_id BIGINT NOT NULL,
|
||
plan_code TEXT NOT NULL,
|
||
start_at TEXT NOT NULL,
|
||
end_at TEXT NOT NULL,
|
||
status TEXT DEFAULT 'active',
|
||
source TEXT NOT NULL,
|
||
order_id BIGINT,
|
||
created_at TEXT NOT NULL,
|
||
updated_at TEXT NOT NULL
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_user_subscription_user ON user_subscription(user_id, status, end_at);
|
||
|
||
CREATE TABLE IF NOT EXISTS payment_order (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
user_id BIGINT NOT NULL,
|
||
plan_code TEXT NOT NULL,
|
||
amount_usdt DOUBLE PRECISION NOT NULL DEFAULT 0,
|
||
chain TEXT NOT NULL DEFAULT 'TRC20',
|
||
pay_address TEXT DEFAULT '',
|
||
txid TEXT DEFAULT '',
|
||
status TEXT NOT NULL DEFAULT 'pending',
|
||
created_at TEXT NOT NULL,
|
||
paid_at TEXT DEFAULT '',
|
||
expire_at TEXT DEFAULT '',
|
||
admin_note TEXT DEFAULT '',
|
||
raw_payload_json TEXT DEFAULT '{}'
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_payment_order_user ON payment_order(user_id, status);
|
||
CREATE INDEX IF NOT EXISTS idx_payment_order_txid ON payment_order(txid);
|
||
CREATE INDEX IF NOT EXISTS idx_payment_order_created ON payment_order(created_at);
|
||
|
||
CREATE TABLE IF NOT EXISTS pending_registration (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
email TEXT NOT NULL,
|
||
code_hash TEXT NOT NULL,
|
||
expires_at TEXT NOT NULL,
|
||
used_at TEXT DEFAULT '',
|
||
created_at TEXT NOT NULL
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_pending_reg_email ON pending_registration(email, used_at);
|
||
|
||
CREATE TABLE IF NOT EXISTS referral_reward (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
inviter_user_id BIGINT NOT NULL,
|
||
invitee_user_id BIGINT NOT NULL,
|
||
order_id BIGINT,
|
||
reward_type TEXT NOT NULL DEFAULT 'days',
|
||
reward_days INTEGER DEFAULT 0,
|
||
reward_amount_usdt DOUBLE PRECISION DEFAULT 0,
|
||
status TEXT DEFAULT 'pending',
|
||
created_at TEXT NOT NULL,
|
||
updated_at TEXT NOT NULL
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS user_activity (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
user_id BIGINT NOT NULL,
|
||
action TEXT NOT NULL,
|
||
page TEXT DEFAULT '',
|
||
ip TEXT DEFAULT '',
|
||
created_at TEXT NOT NULL
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_ua_user ON user_activity(user_id, created_at);
|
||
CREATE INDEX IF NOT EXISTS idx_ua_date ON user_activity(created_at);
|
||
|
||
CREATE TABLE IF NOT EXISTS user_watchlist (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
user_id BIGINT NOT NULL,
|
||
symbol TEXT NOT NULL,
|
||
created_at TEXT NOT NULL,
|
||
UNIQUE(user_id, symbol)
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_user_watchlist_user ON user_watchlist(user_id, symbol);
|
||
|
||
CREATE TABLE IF NOT EXISTS user_saved_observation (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
user_id BIGINT NOT NULL,
|
||
rec_id BIGINT NOT NULL,
|
||
note TEXT DEFAULT '',
|
||
created_at TEXT NOT NULL,
|
||
updated_at TEXT NOT NULL,
|
||
UNIQUE(user_id, rec_id)
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_saved_obs_user ON user_saved_observation(user_id, rec_id);
|
||
|
||
CREATE TABLE IF NOT EXISTS user_push_rule (
|
||
user_id BIGINT PRIMARY KEY,
|
||
watchlist_only INTEGER DEFAULT 0,
|
||
min_score INTEGER DEFAULT 0,
|
||
min_rr DOUBLE PRECISION DEFAULT 0,
|
||
push_buy_now INTEGER DEFAULT 1,
|
||
push_wait_pullback INTEGER DEFAULT 1,
|
||
push_observe INTEGER DEFAULT 0,
|
||
quiet_start TEXT DEFAULT '',
|
||
quiet_end TEXT DEFAULT '',
|
||
updated_at TEXT NOT NULL
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS system_reset_log (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
reset_at TEXT NOT NULL,
|
||
reason TEXT DEFAULT '',
|
||
backup_path TEXT DEFAULT '',
|
||
counts_json TEXT DEFAULT '{}'
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_system_reset_log_time ON system_reset_log(reset_at DESC);
|
||
|
||
CREATE TABLE IF NOT EXISTS scheduler_job_config (
|
||
job_name TEXT PRIMARY KEY,
|
||
command TEXT NOT NULL,
|
||
args_json TEXT DEFAULT '[]',
|
||
enabled INTEGER DEFAULT 1,
|
||
every_seconds INTEGER NOT NULL,
|
||
initial_delay INTEGER DEFAULT 0,
|
||
lock_group TEXT DEFAULT '',
|
||
description TEXT DEFAULT '',
|
||
sort_order INTEGER DEFAULT 0,
|
||
created_at TEXT NOT NULL,
|
||
updated_at TEXT NOT NULL
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS scheduler_runtime_status (
|
||
job_name TEXT PRIMARY KEY,
|
||
status TEXT DEFAULT 'idle',
|
||
pid INTEGER DEFAULT 0,
|
||
run_kind TEXT DEFAULT '',
|
||
trigger_id BIGINT DEFAULT 0,
|
||
locked_by TEXT DEFAULT '',
|
||
next_run_at TEXT DEFAULT '',
|
||
last_started_at TEXT DEFAULT '',
|
||
last_finished_at TEXT DEFAULT '',
|
||
last_exit_code INTEGER DEFAULT 0,
|
||
last_duration_ms INTEGER DEFAULT 0,
|
||
last_error TEXT DEFAULT '',
|
||
output_tail TEXT DEFAULT '',
|
||
updated_at TEXT NOT NULL
|
||
);
|
||
|
||
CREATE TABLE IF NOT EXISTS scheduler_manual_trigger (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
job_name TEXT NOT NULL,
|
||
force INTEGER DEFAULT 0,
|
||
status TEXT DEFAULT 'queued',
|
||
requested_by TEXT DEFAULT '',
|
||
requested_at TEXT NOT NULL,
|
||
started_at TEXT DEFAULT '',
|
||
finished_at TEXT DEFAULT '',
|
||
exit_code INTEGER DEFAULT 0,
|
||
duration_ms INTEGER DEFAULT 0,
|
||
output_tail TEXT DEFAULT '',
|
||
error_message TEXT DEFAULT ''
|
||
);
|
||
CREATE INDEX IF NOT EXISTS idx_scheduler_trigger_status ON scheduler_manual_trigger(status, requested_at);
|