trading-platform-database-v2/ddl/schemas/financial/tables/05-payments.sql
rckrdmrd 45e77e9a9c feat: Initial commit - Database schemas and scripts
DDL schemas for Trading Platform:
- User management
- Authentication
- Payments
- Education
- ML predictions
- Trading data

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-18 04:30:23 -06:00

87 lines
3.6 KiB
SQL

-- =====================================================
-- ORBIQUANT IA - PAYMENTS TABLE
-- =====================================================
-- Description: Payment transaction records
-- Schema: financial
-- =====================================================
CREATE TABLE financial.payments (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
-- Referencias
user_id UUID NOT NULL REFERENCES auth.users(id) ON DELETE RESTRICT,
subscription_id UUID REFERENCES financial.subscriptions(id) ON DELETE SET NULL,
invoice_id UUID REFERENCES financial.invoices(id) ON DELETE SET NULL,
wallet_transaction_id UUID REFERENCES financial.wallet_transactions(id) ON DELETE SET NULL,
-- Stripe integration
stripe_payment_intent_id VARCHAR(255) UNIQUE,
stripe_charge_id VARCHAR(255),
stripe_payment_method_id VARCHAR(255),
-- Payment details
amount DECIMAL(15,2) NOT NULL,
currency financial.currency_code NOT NULL,
payment_method financial.payment_method NOT NULL,
status financial.payment_status NOT NULL DEFAULT 'pending',
-- Descripción
description TEXT,
statement_descriptor VARCHAR(255), -- Lo que ve el usuario en su estado de cuenta
-- Refunds
refunded BOOLEAN DEFAULT false,
refund_amount DECIMAL(15,2),
refund_reason TEXT,
refunded_at TIMESTAMPTZ,
-- Metadata
metadata JSONB DEFAULT '{}',
-- Error handling
failure_code VARCHAR(100),
failure_message TEXT,
-- Timestamps
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
succeeded_at TIMESTAMPTZ,
failed_at TIMESTAMPTZ,
-- Constraints
CONSTRAINT positive_amount CHECK (amount > 0),
CONSTRAINT positive_refund CHECK (refund_amount IS NULL OR refund_amount > 0),
CONSTRAINT refund_lte_amount CHECK (refund_amount IS NULL OR refund_amount <= amount),
CONSTRAINT refunded_has_data CHECK (
(refunded = false AND refund_amount IS NULL AND refunded_at IS NULL) OR
(refunded = true AND refund_amount IS NOT NULL AND refunded_at IS NOT NULL)
),
CONSTRAINT succeeded_has_timestamp CHECK (
(status = 'succeeded' AND succeeded_at IS NOT NULL) OR
(status != 'succeeded')
),
CONSTRAINT failed_has_data CHECK (
(status = 'failed' AND failed_at IS NOT NULL) OR
(status != 'failed')
)
);
-- Indexes
CREATE INDEX idx_payments_user_id ON financial.payments(user_id);
CREATE INDEX idx_payments_subscription_id ON financial.payments(subscription_id) WHERE subscription_id IS NOT NULL;
CREATE INDEX idx_payments_invoice_id ON financial.payments(invoice_id) WHERE invoice_id IS NOT NULL;
CREATE INDEX idx_payments_status ON financial.payments(status);
CREATE INDEX idx_payments_stripe_intent ON financial.payments(stripe_payment_intent_id) WHERE stripe_payment_intent_id IS NOT NULL;
CREATE INDEX idx_payments_created_at ON financial.payments(created_at DESC);
CREATE INDEX idx_payments_user_created ON financial.payments(user_id, created_at DESC);
CREATE INDEX idx_payments_payment_method ON financial.payments(payment_method);
CREATE INDEX idx_payments_refunded ON financial.payments(refunded) WHERE refunded = true;
-- Comments
COMMENT ON TABLE financial.payments IS 'Payment transaction records with Stripe integration';
COMMENT ON COLUMN financial.payments.stripe_payment_intent_id IS 'Stripe PaymentIntent ID';
COMMENT ON COLUMN financial.payments.payment_method IS 'Payment method used: card, bank_transfer, crypto, etc.';
COMMENT ON COLUMN financial.payments.statement_descriptor IS 'Text shown on customer bank statement';
COMMENT ON COLUMN financial.payments.wallet_transaction_id IS 'Related wallet transaction if payment funds a wallet';
COMMENT ON COLUMN financial.payments.metadata IS 'Additional payment metadata and context';