diff --git a/ddl/schemas/auth/tables/11-notifications.sql b/ddl/schemas/auth/tables/11-notifications.sql new file mode 100644 index 0000000..2eae0ba --- /dev/null +++ b/ddl/schemas/auth/tables/11-notifications.sql @@ -0,0 +1,73 @@ +-- ============================================================================ +-- OrbiQuant IA - Trading Platform +-- Schema: auth +-- File: tables/11-notifications.sql +-- Description: User notifications for alerts, trades, distributions, etc. +-- ============================================================================ + +CREATE TABLE auth.notifications ( + -- Primary Key + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + + -- Foreign Key to Users + user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE, + + -- Notification Content + type VARCHAR(50) NOT NULL, + title VARCHAR(255) NOT NULL, + message TEXT NOT NULL, + priority VARCHAR(20) NOT NULL DEFAULT 'normal', + + -- Additional Data + data JSONB, + action_url VARCHAR(500), + icon_type VARCHAR(20) DEFAULT 'info', + + -- Delivery + channels TEXT[] NOT NULL DEFAULT '{}', + + -- Read Status + is_read BOOLEAN NOT NULL DEFAULT FALSE, + read_at TIMESTAMPTZ, + + -- Audit + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + + -- Constraints + CONSTRAINT valid_priority CHECK (priority IN ('low', 'normal', 'high', 'urgent')), + CONSTRAINT valid_type CHECK (type IN ( + 'alert_triggered', + 'trade_executed', + 'deposit_confirmed', + 'withdrawal_completed', + 'distribution_received', + 'system_announcement', + 'security_alert', + 'account_update' + )), + CONSTRAINT valid_icon_type CHECK (icon_type IN ('success', 'warning', 'error', 'info')) +); + +-- Indexes for Performance +CREATE INDEX idx_notifications_user_id ON auth.notifications(user_id); +CREATE INDEX idx_notifications_created_at ON auth.notifications(created_at DESC); +CREATE INDEX idx_notifications_unread ON auth.notifications(user_id) WHERE is_read = FALSE; +CREATE INDEX idx_notifications_type ON auth.notifications(type); + +-- Table Comments +COMMENT ON TABLE auth.notifications IS 'User notifications for various platform events'; + +-- Column Comments +COMMENT ON COLUMN auth.notifications.id IS 'Unique identifier for the notification'; +COMMENT ON COLUMN auth.notifications.user_id IS 'Reference to the user receiving the notification'; +COMMENT ON COLUMN auth.notifications.type IS 'Type of notification (alert_triggered, trade_executed, etc.)'; +COMMENT ON COLUMN auth.notifications.title IS 'Notification title displayed to user'; +COMMENT ON COLUMN auth.notifications.message IS 'Full notification message content'; +COMMENT ON COLUMN auth.notifications.priority IS 'Notification priority (low, normal, high, urgent)'; +COMMENT ON COLUMN auth.notifications.data IS 'Additional structured data as JSON'; +COMMENT ON COLUMN auth.notifications.action_url IS 'URL to navigate when notification is clicked'; +COMMENT ON COLUMN auth.notifications.icon_type IS 'Icon type to display (success, warning, error, info)'; +COMMENT ON COLUMN auth.notifications.channels IS 'Delivery channels used (push, email, in_app, sms)'; +COMMENT ON COLUMN auth.notifications.is_read IS 'Whether the notification has been read'; +COMMENT ON COLUMN auth.notifications.read_at IS 'Timestamp when notification was read'; +COMMENT ON COLUMN auth.notifications.created_at IS 'Timestamp when notification was created'; diff --git a/ddl/schemas/auth/tables/12-user_push_tokens.sql b/ddl/schemas/auth/tables/12-user_push_tokens.sql new file mode 100644 index 0000000..6057871 --- /dev/null +++ b/ddl/schemas/auth/tables/12-user_push_tokens.sql @@ -0,0 +1,51 @@ +-- ============================================================================ +-- OrbiQuant IA - Trading Platform +-- Schema: auth +-- File: tables/12-user_push_tokens.sql +-- Description: User push notification tokens for FCM/APNs/Web Push +-- ============================================================================ + +CREATE TABLE auth.user_push_tokens ( + -- Primary Key + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + + -- Foreign Key to Users + user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE CASCADE, + + -- Token Information + token TEXT NOT NULL, + platform VARCHAR(20) NOT NULL, + + -- Device Information + device_info JSONB, + + -- Status + is_active BOOLEAN NOT NULL DEFAULT TRUE, + last_used_at TIMESTAMPTZ, + + -- Audit + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + + -- Constraints + CONSTRAINT valid_platform CHECK (platform IN ('web', 'ios', 'android')), + CONSTRAINT unique_token UNIQUE (token) +); + +-- Indexes for Performance +CREATE INDEX idx_push_tokens_user ON auth.user_push_tokens(user_id) WHERE is_active = TRUE; +CREATE INDEX idx_push_tokens_platform ON auth.user_push_tokens(platform); + +-- Table Comments +COMMENT ON TABLE auth.user_push_tokens IS 'Push notification tokens for FCM, APNs, and Web Push'; + +-- Column Comments +COMMENT ON COLUMN auth.user_push_tokens.id IS 'Unique identifier for the token record'; +COMMENT ON COLUMN auth.user_push_tokens.user_id IS 'Reference to the user owning this token'; +COMMENT ON COLUMN auth.user_push_tokens.token IS 'The push notification token string'; +COMMENT ON COLUMN auth.user_push_tokens.platform IS 'Platform type (web, ios, android)'; +COMMENT ON COLUMN auth.user_push_tokens.device_info IS 'Device metadata as JSON (model, os_version, app_version, etc.)'; +COMMENT ON COLUMN auth.user_push_tokens.is_active IS 'Whether the token is currently valid'; +COMMENT ON COLUMN auth.user_push_tokens.last_used_at IS 'Timestamp of last successful notification sent'; +COMMENT ON COLUMN auth.user_push_tokens.created_at IS 'Timestamp when token was registered'; +COMMENT ON COLUMN auth.user_push_tokens.updated_at IS 'Timestamp when token was last updated'; diff --git a/ddl/schemas/investment/tables/08-distribution_history.sql b/ddl/schemas/investment/tables/08-distribution_history.sql new file mode 100644 index 0000000..3ec1af0 --- /dev/null +++ b/ddl/schemas/investment/tables/08-distribution_history.sql @@ -0,0 +1,55 @@ +-- ============================================================================ +-- OrbiQuant IA - Trading Platform +-- Schema: investment +-- File: tables/08-distribution_history.sql +-- Description: Daily distribution history per account +-- ============================================================================ + +CREATE TABLE investment.distribution_history ( + -- Primary Key + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + + -- Foreign Keys + account_id UUID NOT NULL REFERENCES investment.accounts(id) ON DELETE CASCADE, + product_id UUID NOT NULL REFERENCES investment.products(id) ON DELETE RESTRICT, + + -- Distribution Period + distribution_date DATE NOT NULL, + + -- Amounts + gross_amount DECIMAL(18,2) NOT NULL, + fee_amount DECIMAL(18,2) NOT NULL DEFAULT 0, + net_amount DECIMAL(18,2) NOT NULL, + + -- Balance Tracking + balance_before DECIMAL(18,2) NOT NULL, + balance_after DECIMAL(18,2) NOT NULL, + + -- Audit + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + + -- Constraints + CONSTRAINT positive_amounts CHECK (gross_amount >= 0 AND net_amount >= 0 AND fee_amount >= 0), + CONSTRAINT unique_daily_distribution UNIQUE (account_id, distribution_date), + CONSTRAINT valid_balance_change CHECK (balance_after = balance_before + net_amount) +); + +-- Indexes for Performance +CREATE INDEX idx_distribution_history_account ON investment.distribution_history(account_id); +CREATE INDEX idx_distribution_history_date ON investment.distribution_history(distribution_date DESC); +CREATE INDEX idx_distribution_history_product ON investment.distribution_history(product_id); + +-- Table Comments +COMMENT ON TABLE investment.distribution_history IS 'Daily distribution records per investment account'; + +-- Column Comments +COMMENT ON COLUMN investment.distribution_history.id IS 'Unique identifier for the distribution record'; +COMMENT ON COLUMN investment.distribution_history.account_id IS 'Reference to the investment account'; +COMMENT ON COLUMN investment.distribution_history.product_id IS 'Reference to the investment product'; +COMMENT ON COLUMN investment.distribution_history.distribution_date IS 'Date of the distribution'; +COMMENT ON COLUMN investment.distribution_history.gross_amount IS 'Gross return before fees'; +COMMENT ON COLUMN investment.distribution_history.fee_amount IS 'Performance fee deducted'; +COMMENT ON COLUMN investment.distribution_history.net_amount IS 'Net amount credited to account'; +COMMENT ON COLUMN investment.distribution_history.balance_before IS 'Account balance before distribution'; +COMMENT ON COLUMN investment.distribution_history.balance_after IS 'Account balance after distribution'; +COMMENT ON COLUMN investment.distribution_history.created_at IS 'Timestamp when record was created'; diff --git a/ddl/schemas/investment/tables/09-distribution_runs.sql b/ddl/schemas/investment/tables/09-distribution_runs.sql new file mode 100644 index 0000000..35e9fa3 --- /dev/null +++ b/ddl/schemas/investment/tables/09-distribution_runs.sql @@ -0,0 +1,65 @@ +-- ============================================================================ +-- OrbiQuant IA - Trading Platform +-- Schema: investment +-- File: tables/09-distribution_runs.sql +-- Description: Distribution job execution logs and summaries +-- ============================================================================ + +CREATE TABLE investment.distribution_runs ( + -- Primary Key + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + + -- Run Information + run_date DATE NOT NULL UNIQUE, + + -- Statistics + total_accounts INTEGER NOT NULL DEFAULT 0, + successful_count INTEGER NOT NULL DEFAULT 0, + failed_count INTEGER NOT NULL DEFAULT 0, + + -- Financial Totals + total_gross_amount DECIMAL(18,2) NOT NULL DEFAULT 0, + total_fee_amount DECIMAL(18,2) NOT NULL DEFAULT 0, + total_net_amount DECIMAL(18,2) NOT NULL DEFAULT 0, + + -- Timing + started_at TIMESTAMPTZ NOT NULL, + completed_at TIMESTAMPTZ, + duration_ms INTEGER, + + -- Error Tracking + error_details JSONB, + + -- Audit + created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), + + -- Constraints + CONSTRAINT valid_counts CHECK ( + successful_count >= 0 AND + failed_count >= 0 AND + total_accounts = successful_count + failed_count + ), + CONSTRAINT valid_duration CHECK (duration_ms IS NULL OR duration_ms >= 0) +); + +-- Indexes for Performance +CREATE INDEX idx_distribution_runs_date ON investment.distribution_runs(run_date DESC); +CREATE INDEX idx_distribution_runs_started ON investment.distribution_runs(started_at DESC); + +-- Table Comments +COMMENT ON TABLE investment.distribution_runs IS 'Distribution job execution logs and performance metrics'; + +-- Column Comments +COMMENT ON COLUMN investment.distribution_runs.id IS 'Unique identifier for the run record'; +COMMENT ON COLUMN investment.distribution_runs.run_date IS 'Date of the distribution run'; +COMMENT ON COLUMN investment.distribution_runs.total_accounts IS 'Total accounts processed'; +COMMENT ON COLUMN investment.distribution_runs.successful_count IS 'Number of successful distributions'; +COMMENT ON COLUMN investment.distribution_runs.failed_count IS 'Number of failed distributions'; +COMMENT ON COLUMN investment.distribution_runs.total_gross_amount IS 'Sum of all gross returns'; +COMMENT ON COLUMN investment.distribution_runs.total_fee_amount IS 'Sum of all performance fees'; +COMMENT ON COLUMN investment.distribution_runs.total_net_amount IS 'Sum of all net distributions'; +COMMENT ON COLUMN investment.distribution_runs.started_at IS 'Timestamp when run started'; +COMMENT ON COLUMN investment.distribution_runs.completed_at IS 'Timestamp when run completed'; +COMMENT ON COLUMN investment.distribution_runs.duration_ms IS 'Run duration in milliseconds'; +COMMENT ON COLUMN investment.distribution_runs.error_details IS 'Error information as JSON if failures occurred'; +COMMENT ON COLUMN investment.distribution_runs.created_at IS 'Timestamp when record was created';