DDL schemas for Trading Platform: - User management - Authentication - Payments - Education - ML predictions - Trading data Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
259 lines
8.3 KiB
SQL
259 lines
8.3 KiB
SQL
-- =====================================================
|
|
-- ORBIQUANT IA - FINANCIAL SCHEMA VIEWS
|
|
-- =====================================================
|
|
-- Description: Useful views for common financial queries
|
|
-- Schema: financial
|
|
-- =====================================================
|
|
|
|
-- =====================================================
|
|
-- VIEW: Active user wallets summary
|
|
-- =====================================================
|
|
|
|
CREATE OR REPLACE VIEW financial.v_user_wallets_summary AS
|
|
SELECT
|
|
w.user_id,
|
|
w.wallet_type,
|
|
w.currency,
|
|
w.balance,
|
|
w.available_balance,
|
|
w.pending_balance,
|
|
w.status,
|
|
w.last_transaction_at,
|
|
w.total_deposits,
|
|
w.total_withdrawals,
|
|
w.created_at,
|
|
-- Transaction counts
|
|
(SELECT COUNT(*)
|
|
FROM financial.wallet_transactions wt
|
|
WHERE wt.wallet_id = w.id AND wt.status = 'completed') as total_transactions,
|
|
(SELECT COUNT(*)
|
|
FROM financial.wallet_transactions wt
|
|
WHERE wt.wallet_id = w.id AND wt.status = 'pending') as pending_transactions,
|
|
-- Latest transaction
|
|
(SELECT wt.created_at
|
|
FROM financial.wallet_transactions wt
|
|
WHERE wt.wallet_id = w.id
|
|
ORDER BY wt.created_at DESC
|
|
LIMIT 1) as last_tx_date
|
|
FROM financial.wallets w
|
|
WHERE w.status = 'active';
|
|
|
|
COMMENT ON VIEW financial.v_user_wallets_summary IS 'Active wallets with transaction statistics';
|
|
|
|
-- =====================================================
|
|
-- VIEW: User total balance across all wallets (USD)
|
|
-- =====================================================
|
|
|
|
CREATE OR REPLACE VIEW financial.v_user_total_balance AS
|
|
SELECT
|
|
user_id,
|
|
SUM(CASE WHEN currency = 'USD' THEN balance ELSE 0 END) as total_usd,
|
|
SUM(CASE WHEN currency = 'MXN' THEN balance ELSE 0 END) as total_mxn,
|
|
SUM(CASE WHEN currency = 'EUR' THEN balance ELSE 0 END) as total_eur,
|
|
-- Totals by wallet type
|
|
SUM(CASE WHEN wallet_type = 'trading' AND currency = 'USD' THEN balance ELSE 0 END) as trading_usd,
|
|
SUM(CASE WHEN wallet_type = 'investment' AND currency = 'USD' THEN balance ELSE 0 END) as investment_usd,
|
|
SUM(CASE WHEN wallet_type = 'earnings' AND currency = 'USD' THEN balance ELSE 0 END) as earnings_usd,
|
|
SUM(CASE WHEN wallet_type = 'referral' AND currency = 'USD' THEN balance ELSE 0 END) as referral_usd,
|
|
COUNT(*) as wallet_count,
|
|
MAX(last_transaction_at) as last_activity
|
|
FROM financial.wallets
|
|
WHERE status = 'active'
|
|
GROUP BY user_id;
|
|
|
|
COMMENT ON VIEW financial.v_user_total_balance IS 'Aggregated balance per user across all wallets';
|
|
|
|
-- =====================================================
|
|
-- VIEW: Recent transactions (last 30 days)
|
|
-- =====================================================
|
|
|
|
CREATE OR REPLACE VIEW financial.v_recent_transactions AS
|
|
SELECT
|
|
wt.id,
|
|
wt.wallet_id,
|
|
w.user_id,
|
|
w.wallet_type,
|
|
wt.transaction_type,
|
|
wt.status,
|
|
wt.amount,
|
|
wt.fee,
|
|
wt.net_amount,
|
|
wt.currency,
|
|
wt.description,
|
|
wt.reference_id,
|
|
wt.balance_before,
|
|
wt.balance_after,
|
|
wt.created_at,
|
|
wt.completed_at,
|
|
-- Days since transaction
|
|
EXTRACT(DAY FROM NOW() - wt.created_at) as days_ago
|
|
FROM financial.wallet_transactions wt
|
|
JOIN financial.wallets w ON w.id = wt.wallet_id
|
|
WHERE wt.created_at >= NOW() - INTERVAL '30 days'
|
|
ORDER BY wt.created_at DESC;
|
|
|
|
COMMENT ON VIEW financial.v_recent_transactions IS 'Wallet transactions from last 30 days';
|
|
|
|
-- =====================================================
|
|
-- VIEW: Active subscriptions with user details
|
|
-- =====================================================
|
|
|
|
CREATE OR REPLACE VIEW financial.v_active_subscriptions AS
|
|
SELECT
|
|
s.id,
|
|
s.user_id,
|
|
s.plan,
|
|
s.status,
|
|
s.price,
|
|
s.currency,
|
|
s.billing_interval,
|
|
s.current_period_start,
|
|
s.current_period_end,
|
|
s.next_payment_at,
|
|
s.cancel_at_period_end,
|
|
s.stripe_subscription_id,
|
|
-- Days until renewal
|
|
EXTRACT(DAY FROM s.current_period_end - NOW()) as days_until_renewal,
|
|
-- Is in trial
|
|
(s.status = 'trialing') as is_trial,
|
|
-- Trial days remaining
|
|
CASE
|
|
WHEN s.trial_end IS NOT NULL THEN EXTRACT(DAY FROM s.trial_end - NOW())
|
|
ELSE NULL
|
|
END as trial_days_remaining
|
|
FROM financial.subscriptions s
|
|
WHERE s.status IN ('active', 'trialing', 'past_due')
|
|
ORDER BY s.current_period_end ASC;
|
|
|
|
COMMENT ON VIEW financial.v_active_subscriptions IS 'Active subscriptions with renewal information';
|
|
|
|
-- =====================================================
|
|
-- VIEW: Pending payments
|
|
-- =====================================================
|
|
|
|
CREATE OR REPLACE VIEW financial.v_pending_payments AS
|
|
SELECT
|
|
p.id,
|
|
p.user_id,
|
|
p.subscription_id,
|
|
p.amount,
|
|
p.currency,
|
|
p.payment_method,
|
|
p.status,
|
|
p.description,
|
|
p.stripe_payment_intent_id,
|
|
p.created_at,
|
|
-- Days pending
|
|
EXTRACT(DAY FROM NOW() - p.created_at) as days_pending
|
|
FROM financial.payments p
|
|
WHERE p.status IN ('pending', 'processing')
|
|
ORDER BY p.created_at ASC;
|
|
|
|
COMMENT ON VIEW financial.v_pending_payments IS 'Payments awaiting completion';
|
|
|
|
-- =====================================================
|
|
-- VIEW: Unpaid invoices
|
|
-- =====================================================
|
|
|
|
CREATE OR REPLACE VIEW financial.v_unpaid_invoices AS
|
|
SELECT
|
|
i.id,
|
|
i.user_id,
|
|
i.invoice_number,
|
|
i.total,
|
|
i.amount_due,
|
|
i.currency,
|
|
i.due_date,
|
|
i.status,
|
|
i.invoice_date,
|
|
i.hosted_invoice_url,
|
|
-- Days overdue
|
|
CASE
|
|
WHEN i.due_date IS NOT NULL AND i.due_date < NOW()
|
|
THEN EXTRACT(DAY FROM NOW() - i.due_date)
|
|
ELSE 0
|
|
END as days_overdue,
|
|
-- Is overdue
|
|
(i.due_date IS NOT NULL AND i.due_date < NOW()) as is_overdue
|
|
FROM financial.invoices i
|
|
WHERE i.status = 'open' AND i.paid = false
|
|
ORDER BY i.due_date ASC NULLS LAST;
|
|
|
|
COMMENT ON VIEW financial.v_unpaid_invoices IS 'Open invoices with overdue status';
|
|
|
|
-- =====================================================
|
|
-- VIEW: Daily transaction volume
|
|
-- =====================================================
|
|
|
|
CREATE OR REPLACE VIEW financial.v_daily_transaction_volume AS
|
|
SELECT
|
|
DATE(wt.created_at) as transaction_date,
|
|
wt.transaction_type,
|
|
wt.currency,
|
|
COUNT(*) as transaction_count,
|
|
SUM(wt.amount) as total_amount,
|
|
SUM(wt.fee) as total_fees,
|
|
SUM(wt.net_amount) as total_net_amount,
|
|
AVG(wt.amount) as avg_amount
|
|
FROM financial.wallet_transactions wt
|
|
WHERE wt.status = 'completed'
|
|
AND wt.created_at >= NOW() - INTERVAL '90 days'
|
|
GROUP BY DATE(wt.created_at), wt.transaction_type, wt.currency
|
|
ORDER BY transaction_date DESC, transaction_type;
|
|
|
|
COMMENT ON VIEW financial.v_daily_transaction_volume IS 'Daily aggregated transaction statistics';
|
|
|
|
-- =====================================================
|
|
-- VIEW: Wallet activity summary (last 7 days)
|
|
-- =====================================================
|
|
|
|
CREATE OR REPLACE VIEW financial.v_wallet_activity_7d AS
|
|
SELECT
|
|
w.id as wallet_id,
|
|
w.user_id,
|
|
w.wallet_type,
|
|
w.currency,
|
|
w.balance,
|
|
-- Transaction counts by type
|
|
COUNT(CASE WHEN wt.transaction_type = 'deposit' THEN 1 END) as deposits_7d,
|
|
COUNT(CASE WHEN wt.transaction_type = 'withdrawal' THEN 1 END) as withdrawals_7d,
|
|
COUNT(CASE WHEN wt.transaction_type IN ('transfer_in', 'transfer_out') THEN 1 END) as transfers_7d,
|
|
-- Amounts
|
|
SUM(CASE WHEN wt.transaction_type = 'deposit' THEN wt.amount ELSE 0 END) as deposit_amount_7d,
|
|
SUM(CASE WHEN wt.transaction_type = 'withdrawal' THEN wt.amount ELSE 0 END) as withdrawal_amount_7d,
|
|
-- Total activity
|
|
COUNT(wt.id) as total_transactions_7d
|
|
FROM financial.wallets w
|
|
LEFT JOIN financial.wallet_transactions wt ON wt.wallet_id = w.id
|
|
AND wt.created_at >= NOW() - INTERVAL '7 days'
|
|
AND wt.status = 'completed'
|
|
WHERE w.status = 'active'
|
|
GROUP BY w.id, w.user_id, w.wallet_type, w.currency, w.balance;
|
|
|
|
COMMENT ON VIEW financial.v_wallet_activity_7d IS 'Wallet activity summary for last 7 days';
|
|
|
|
-- =====================================================
|
|
-- VIEW: Subscription revenue metrics
|
|
-- =====================================================
|
|
|
|
CREATE OR REPLACE VIEW financial.v_subscription_revenue AS
|
|
SELECT
|
|
s.plan,
|
|
s.billing_interval,
|
|
s.currency,
|
|
COUNT(*) as active_count,
|
|
SUM(s.price) as total_monthly_value,
|
|
AVG(s.price) as avg_price,
|
|
-- MRR calculation (Monthly Recurring Revenue)
|
|
SUM(CASE
|
|
WHEN s.billing_interval = 'month' THEN s.price
|
|
WHEN s.billing_interval = 'year' THEN s.price / 12
|
|
ELSE 0
|
|
END) as monthly_recurring_revenue
|
|
FROM financial.subscriptions s
|
|
WHERE s.status IN ('active', 'trialing')
|
|
GROUP BY s.plan, s.billing_interval, s.currency
|
|
ORDER BY s.plan, s.billing_interval;
|
|
|
|
COMMENT ON VIEW financial.v_subscription_revenue IS 'Subscription metrics and MRR calculation';
|