521 lines
18 KiB
PL/PgSQL
521 lines
18 KiB
PL/PgSQL
-- ============================================================================
|
|
-- SCHEMA: investment
|
|
-- TABLES: agent_allocations, allocation_transactions, profit_distributions
|
|
-- DESCRIPTION: Sistema de fondeo de Money Manager Agents desde Wallet
|
|
-- VERSION: 1.0.0
|
|
-- CREATED: 2026-01-10
|
|
-- DEPENDS: financial.wallets, agents (existing)
|
|
-- ============================================================================
|
|
|
|
-- Crear schema si no existe
|
|
CREATE SCHEMA IF NOT EXISTS investment;
|
|
|
|
-- Enum para tipo de agente
|
|
DO $$ BEGIN
|
|
CREATE TYPE investment.agent_type AS ENUM (
|
|
'ATLAS', -- Conservador - bajo riesgo
|
|
'ORION', -- Moderado - riesgo medio
|
|
'NOVA' -- Agresivo - alto riesgo
|
|
);
|
|
EXCEPTION WHEN duplicate_object THEN null; END $$;
|
|
|
|
-- Enum para estado de allocation
|
|
DO $$ BEGIN
|
|
CREATE TYPE investment.allocation_status AS ENUM (
|
|
'pending', -- Esperando confirmacion
|
|
'active', -- Activa y operando
|
|
'paused', -- Pausada por usuario
|
|
'liquidating', -- En proceso de liquidacion
|
|
'closed' -- Cerrada
|
|
);
|
|
EXCEPTION WHEN duplicate_object THEN null; END $$;
|
|
|
|
-- Enum para tipo de transaccion de allocation
|
|
DO $$ BEGIN
|
|
CREATE TYPE investment.allocation_tx_type AS ENUM (
|
|
'INITIAL_FUNDING', -- Fondeo inicial
|
|
'ADDITIONAL_FUNDING', -- Fondeo adicional
|
|
'PARTIAL_WITHDRAWAL', -- Retiro parcial
|
|
'FULL_WITHDRAWAL', -- Retiro total
|
|
'PROFIT_REALIZED', -- Ganancia realizada
|
|
'LOSS_REALIZED', -- Perdida realizada
|
|
'FEE_CHARGED', -- Comision cobrada
|
|
'REBALANCE' -- Rebalanceo
|
|
);
|
|
EXCEPTION WHEN duplicate_object THEN null; END $$;
|
|
|
|
-- Tabla principal de allocations (fondeo a agentes)
|
|
CREATE TABLE IF NOT EXISTS investment.agent_allocations (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL,
|
|
user_id UUID NOT NULL,
|
|
wallet_id UUID NOT NULL,
|
|
|
|
-- Agente
|
|
agent_type investment.agent_type NOT NULL,
|
|
agent_instance_id UUID, -- Referencia a instancia especifica del agente
|
|
|
|
-- Montos
|
|
initial_amount DECIMAL(15, 4) NOT NULL CHECK (initial_amount > 0),
|
|
current_amount DECIMAL(15, 4) NOT NULL CHECK (current_amount >= 0),
|
|
total_deposited DECIMAL(15, 4) NOT NULL DEFAULT 0,
|
|
total_withdrawn DECIMAL(15, 4) NOT NULL DEFAULT 0,
|
|
|
|
-- Performance
|
|
total_profit DECIMAL(15, 4) NOT NULL DEFAULT 0,
|
|
total_loss DECIMAL(15, 4) NOT NULL DEFAULT 0,
|
|
realized_pnl DECIMAL(15, 4) GENERATED ALWAYS AS (total_profit - total_loss) STORED,
|
|
unrealized_pnl DECIMAL(15, 4) DEFAULT 0,
|
|
|
|
-- Metricas
|
|
roi_percentage DECIMAL(10, 4) DEFAULT 0,
|
|
max_drawdown DECIMAL(10, 4) DEFAULT 0,
|
|
win_rate DECIMAL(5, 2) DEFAULT 0,
|
|
total_trades INT DEFAULT 0,
|
|
winning_trades INT DEFAULT 0,
|
|
losing_trades INT DEFAULT 0,
|
|
|
|
-- Configuracion
|
|
risk_level VARCHAR(20), -- LOW, MEDIUM, HIGH
|
|
auto_compound BOOLEAN DEFAULT FALSE,
|
|
compound_threshold DECIMAL(15, 4) DEFAULT 100,
|
|
|
|
-- Limites
|
|
max_allocation DECIMAL(15, 4),
|
|
stop_loss_percentage DECIMAL(5, 2) DEFAULT 20,
|
|
take_profit_percentage DECIMAL(5, 2),
|
|
|
|
-- Estado
|
|
status investment.allocation_status NOT NULL DEFAULT 'pending',
|
|
|
|
-- Fechas importantes
|
|
activated_at TIMESTAMPTZ,
|
|
last_trade_at TIMESTAMPTZ,
|
|
paused_at TIMESTAMPTZ,
|
|
closed_at TIMESTAMPTZ,
|
|
|
|
-- Metadata
|
|
metadata JSONB DEFAULT '{}',
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
|
|
|
-- Un usuario puede tener multiples allocations al mismo agente
|
|
-- pero con limites
|
|
CONSTRAINT positive_performance CHECK (
|
|
total_deposited >= total_withdrawn
|
|
OR status IN ('closed', 'liquidating')
|
|
)
|
|
);
|
|
|
|
COMMENT ON TABLE investment.agent_allocations IS
|
|
'Fondeos de usuarios a Money Manager Agents (Atlas, Orion, Nova)';
|
|
|
|
-- Tabla de transacciones de allocation
|
|
CREATE TABLE IF NOT EXISTS investment.allocation_transactions (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
allocation_id UUID NOT NULL REFERENCES investment.agent_allocations(id),
|
|
tenant_id UUID NOT NULL,
|
|
|
|
-- Tipo
|
|
type investment.allocation_tx_type NOT NULL,
|
|
|
|
-- Montos
|
|
amount DECIMAL(15, 4) NOT NULL,
|
|
balance_before DECIMAL(15, 4) NOT NULL,
|
|
balance_after DECIMAL(15, 4) NOT NULL,
|
|
|
|
-- Referencia a wallet transaction
|
|
wallet_transaction_id UUID,
|
|
|
|
-- Para trades
|
|
trade_id UUID,
|
|
trade_symbol VARCHAR(20),
|
|
trade_pnl DECIMAL(15, 4),
|
|
|
|
-- Descripcion
|
|
description TEXT,
|
|
|
|
-- Metadata
|
|
metadata JSONB DEFAULT '{}',
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
COMMENT ON TABLE investment.allocation_transactions IS
|
|
'Historial de todas las transacciones en allocations de agentes';
|
|
|
|
-- Tabla de distribuciones de profit
|
|
CREATE TABLE IF NOT EXISTS investment.profit_distributions (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
allocation_id UUID NOT NULL REFERENCES investment.agent_allocations(id),
|
|
tenant_id UUID NOT NULL,
|
|
user_id UUID NOT NULL,
|
|
|
|
-- Periodo
|
|
period_start TIMESTAMPTZ NOT NULL,
|
|
period_end TIMESTAMPTZ NOT NULL,
|
|
|
|
-- Montos
|
|
gross_profit DECIMAL(15, 4) NOT NULL,
|
|
platform_fee DECIMAL(15, 4) NOT NULL DEFAULT 0,
|
|
agent_fee DECIMAL(15, 4) NOT NULL DEFAULT 0,
|
|
net_profit DECIMAL(15, 4) NOT NULL,
|
|
|
|
-- Fee percentages aplicados
|
|
platform_fee_rate DECIMAL(5, 4) DEFAULT 0.10, -- 10%
|
|
agent_fee_rate DECIMAL(5, 4) DEFAULT 0.20, -- 20%
|
|
|
|
-- Distribucion
|
|
distributed_to_wallet BOOLEAN DEFAULT FALSE,
|
|
wallet_transaction_id UUID,
|
|
distributed_at TIMESTAMPTZ,
|
|
|
|
-- Compounding
|
|
compounded_amount DECIMAL(15, 4) DEFAULT 0,
|
|
|
|
created_at TIMESTAMPTZ DEFAULT NOW()
|
|
);
|
|
|
|
COMMENT ON TABLE investment.profit_distributions IS
|
|
'Distribuciones periodicas de ganancias de agentes a usuarios';
|
|
|
|
-- Tabla de configuracion de agentes por tenant
|
|
CREATE TABLE IF NOT EXISTS investment.agent_configs (
|
|
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
tenant_id UUID NOT NULL,
|
|
|
|
agent_type investment.agent_type NOT NULL,
|
|
|
|
-- Limites
|
|
min_allocation DECIMAL(15, 4) DEFAULT 100,
|
|
max_allocation_per_user DECIMAL(15, 4) DEFAULT 10000,
|
|
max_total_allocation DECIMAL(15, 4) DEFAULT 1000000,
|
|
|
|
-- Fees
|
|
platform_fee_rate DECIMAL(5, 4) DEFAULT 0.10,
|
|
performance_fee_rate DECIMAL(5, 4) DEFAULT 0.20,
|
|
|
|
-- Estado
|
|
is_active BOOLEAN DEFAULT TRUE,
|
|
accepting_new_allocations BOOLEAN DEFAULT TRUE,
|
|
|
|
-- Descripcion
|
|
description TEXT,
|
|
risk_disclosure TEXT,
|
|
|
|
-- Stats agregados
|
|
total_users INT DEFAULT 0,
|
|
total_allocated DECIMAL(15, 4) DEFAULT 0,
|
|
total_profit_generated DECIMAL(15, 4) DEFAULT 0,
|
|
|
|
created_at TIMESTAMPTZ DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ DEFAULT NOW(),
|
|
|
|
UNIQUE(tenant_id, agent_type)
|
|
);
|
|
|
|
COMMENT ON TABLE investment.agent_configs IS
|
|
'Configuracion de Money Manager Agents por tenant';
|
|
|
|
-- Indices para agent_allocations
|
|
CREATE INDEX IF NOT EXISTS idx_alloc_tenant ON investment.agent_allocations(tenant_id);
|
|
CREATE INDEX IF NOT EXISTS idx_alloc_user ON investment.agent_allocations(user_id);
|
|
CREATE INDEX IF NOT EXISTS idx_alloc_wallet ON investment.agent_allocations(wallet_id);
|
|
CREATE INDEX IF NOT EXISTS idx_alloc_agent ON investment.agent_allocations(agent_type);
|
|
CREATE INDEX IF NOT EXISTS idx_alloc_status ON investment.agent_allocations(status);
|
|
CREATE INDEX IF NOT EXISTS idx_alloc_active ON investment.agent_allocations(status, agent_type)
|
|
WHERE status = 'active';
|
|
|
|
-- Indices para allocation_transactions
|
|
CREATE INDEX IF NOT EXISTS idx_alloc_tx_alloc ON investment.allocation_transactions(allocation_id);
|
|
CREATE INDEX IF NOT EXISTS idx_alloc_tx_tenant ON investment.allocation_transactions(tenant_id);
|
|
CREATE INDEX IF NOT EXISTS idx_alloc_tx_type ON investment.allocation_transactions(type);
|
|
CREATE INDEX IF NOT EXISTS idx_alloc_tx_created ON investment.allocation_transactions(created_at DESC);
|
|
|
|
-- Indices para profit_distributions
|
|
CREATE INDEX IF NOT EXISTS idx_profit_dist_alloc ON investment.profit_distributions(allocation_id);
|
|
CREATE INDEX IF NOT EXISTS idx_profit_dist_user ON investment.profit_distributions(user_id);
|
|
CREATE INDEX IF NOT EXISTS idx_profit_dist_period ON investment.profit_distributions(period_start, period_end);
|
|
CREATE INDEX IF NOT EXISTS idx_profit_dist_pending ON investment.profit_distributions(distributed_to_wallet)
|
|
WHERE distributed_to_wallet = FALSE;
|
|
|
|
-- Trigger updated_at
|
|
CREATE OR REPLACE FUNCTION investment.update_timestamp()
|
|
RETURNS TRIGGER AS $$
|
|
BEGIN
|
|
NEW.updated_at = NOW();
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
DROP TRIGGER IF EXISTS alloc_updated ON investment.agent_allocations;
|
|
CREATE TRIGGER alloc_updated
|
|
BEFORE UPDATE ON investment.agent_allocations
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION investment.update_timestamp();
|
|
|
|
DROP TRIGGER IF EXISTS agent_config_updated ON investment.agent_configs;
|
|
CREATE TRIGGER agent_config_updated
|
|
BEFORE UPDATE ON investment.agent_configs
|
|
FOR EACH ROW
|
|
EXECUTE FUNCTION investment.update_timestamp();
|
|
|
|
-- Funcion para crear allocation (fondear agente)
|
|
CREATE OR REPLACE FUNCTION investment.create_allocation(
|
|
p_tenant_id UUID,
|
|
p_user_id UUID,
|
|
p_wallet_id UUID,
|
|
p_agent_type investment.agent_type,
|
|
p_amount DECIMAL(15, 4),
|
|
p_auto_compound BOOLEAN DEFAULT FALSE
|
|
)
|
|
RETURNS UUID AS $$
|
|
DECLARE
|
|
v_config investment.agent_configs%ROWTYPE;
|
|
v_allocation_id UUID;
|
|
v_wallet_tx_id UUID;
|
|
BEGIN
|
|
-- Get agent config
|
|
SELECT * INTO v_config
|
|
FROM investment.agent_configs
|
|
WHERE tenant_id = p_tenant_id
|
|
AND agent_type = p_agent_type;
|
|
|
|
IF NOT FOUND OR NOT v_config.is_active THEN
|
|
RAISE EXCEPTION 'Agent % is not available', p_agent_type;
|
|
END IF;
|
|
|
|
IF NOT v_config.accepting_new_allocations THEN
|
|
RAISE EXCEPTION 'Agent % is not accepting new allocations', p_agent_type;
|
|
END IF;
|
|
|
|
IF p_amount < v_config.min_allocation THEN
|
|
RAISE EXCEPTION 'Minimum allocation is %', v_config.min_allocation;
|
|
END IF;
|
|
|
|
IF p_amount > v_config.max_allocation_per_user THEN
|
|
RAISE EXCEPTION 'Maximum allocation per user is %', v_config.max_allocation_per_user;
|
|
END IF;
|
|
|
|
-- Debit from wallet (this validates balance)
|
|
v_wallet_tx_id := financial.create_wallet_transaction(
|
|
p_wallet_id,
|
|
'AGENT_FUNDING',
|
|
-p_amount,
|
|
'Funding to ' || p_agent_type || ' agent',
|
|
'agent_allocation',
|
|
NULL,
|
|
jsonb_build_object('agent_type', p_agent_type)
|
|
);
|
|
|
|
-- Create allocation
|
|
INSERT INTO investment.agent_allocations (
|
|
tenant_id, user_id, wallet_id, agent_type,
|
|
initial_amount, current_amount, total_deposited,
|
|
auto_compound, risk_level, status
|
|
) VALUES (
|
|
p_tenant_id, p_user_id, p_wallet_id, p_agent_type,
|
|
p_amount, p_amount, p_amount,
|
|
p_auto_compound,
|
|
CASE p_agent_type
|
|
WHEN 'ATLAS' THEN 'LOW'
|
|
WHEN 'ORION' THEN 'MEDIUM'
|
|
WHEN 'NOVA' THEN 'HIGH'
|
|
END,
|
|
'active'
|
|
) RETURNING id INTO v_allocation_id;
|
|
|
|
-- Update allocation with wallet tx reference
|
|
UPDATE investment.agent_allocations
|
|
SET activated_at = NOW(),
|
|
metadata = jsonb_build_object('initial_wallet_tx', v_wallet_tx_id)
|
|
WHERE id = v_allocation_id;
|
|
|
|
-- Record allocation transaction
|
|
INSERT INTO investment.allocation_transactions (
|
|
allocation_id, tenant_id, type,
|
|
amount, balance_before, balance_after,
|
|
wallet_transaction_id, description
|
|
) VALUES (
|
|
v_allocation_id, p_tenant_id, 'INITIAL_FUNDING',
|
|
p_amount, 0, p_amount,
|
|
v_wallet_tx_id, 'Initial funding'
|
|
);
|
|
|
|
-- Update agent config stats
|
|
UPDATE investment.agent_configs
|
|
SET total_users = total_users + 1,
|
|
total_allocated = total_allocated + p_amount
|
|
WHERE tenant_id = p_tenant_id AND agent_type = p_agent_type;
|
|
|
|
RETURN v_allocation_id;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
-- Funcion para retirar de allocation
|
|
CREATE OR REPLACE FUNCTION investment.withdraw_from_allocation(
|
|
p_allocation_id UUID,
|
|
p_amount DECIMAL(15, 4),
|
|
p_full_withdrawal BOOLEAN DEFAULT FALSE
|
|
)
|
|
RETURNS UUID AS $$
|
|
DECLARE
|
|
v_alloc investment.agent_allocations%ROWTYPE;
|
|
v_wallet_tx_id UUID;
|
|
v_withdraw_amount DECIMAL(15, 4);
|
|
v_tx_type investment.allocation_tx_type;
|
|
BEGIN
|
|
-- Lock allocation
|
|
SELECT * INTO v_alloc
|
|
FROM investment.agent_allocations
|
|
WHERE id = p_allocation_id
|
|
FOR UPDATE;
|
|
|
|
IF NOT FOUND THEN
|
|
RAISE EXCEPTION 'Allocation not found';
|
|
END IF;
|
|
|
|
IF v_alloc.status NOT IN ('active', 'paused') THEN
|
|
RAISE EXCEPTION 'Cannot withdraw from allocation in status %', v_alloc.status;
|
|
END IF;
|
|
|
|
-- Determine withdrawal amount
|
|
IF p_full_withdrawal THEN
|
|
v_withdraw_amount := v_alloc.current_amount;
|
|
v_tx_type := 'FULL_WITHDRAWAL';
|
|
ELSE
|
|
IF p_amount > v_alloc.current_amount THEN
|
|
RAISE EXCEPTION 'Insufficient balance. Available: %', v_alloc.current_amount;
|
|
END IF;
|
|
v_withdraw_amount := p_amount;
|
|
v_tx_type := 'PARTIAL_WITHDRAWAL';
|
|
END IF;
|
|
|
|
-- Credit to wallet
|
|
v_wallet_tx_id := financial.create_wallet_transaction(
|
|
v_alloc.wallet_id,
|
|
'AGENT_WITHDRAWAL',
|
|
v_withdraw_amount,
|
|
'Withdrawal from ' || v_alloc.agent_type || ' agent',
|
|
'agent_allocation',
|
|
p_allocation_id,
|
|
jsonb_build_object('agent_type', v_alloc.agent_type)
|
|
);
|
|
|
|
-- Record transaction
|
|
INSERT INTO investment.allocation_transactions (
|
|
allocation_id, tenant_id, type,
|
|
amount, balance_before, balance_after,
|
|
wallet_transaction_id, description
|
|
) VALUES (
|
|
p_allocation_id, v_alloc.tenant_id, v_tx_type,
|
|
-v_withdraw_amount, v_alloc.current_amount,
|
|
v_alloc.current_amount - v_withdraw_amount,
|
|
v_wallet_tx_id,
|
|
CASE WHEN p_full_withdrawal THEN 'Full withdrawal' ELSE 'Partial withdrawal' END
|
|
);
|
|
|
|
-- Update allocation
|
|
UPDATE investment.agent_allocations
|
|
SET current_amount = current_amount - v_withdraw_amount,
|
|
total_withdrawn = total_withdrawn + v_withdraw_amount,
|
|
status = CASE WHEN p_full_withdrawal THEN 'closed' ELSE status END,
|
|
closed_at = CASE WHEN p_full_withdrawal THEN NOW() ELSE closed_at END
|
|
WHERE id = p_allocation_id;
|
|
|
|
-- Update agent config stats
|
|
UPDATE investment.agent_configs
|
|
SET total_allocated = total_allocated - v_withdraw_amount,
|
|
total_users = CASE WHEN p_full_withdrawal THEN total_users - 1 ELSE total_users END
|
|
WHERE tenant_id = v_alloc.tenant_id AND agent_type = v_alloc.agent_type;
|
|
|
|
RETURN v_wallet_tx_id;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
-- Funcion para registrar profit/loss de trade
|
|
CREATE OR REPLACE FUNCTION investment.record_trade_result(
|
|
p_allocation_id UUID,
|
|
p_trade_id UUID,
|
|
p_symbol VARCHAR(20),
|
|
p_pnl DECIMAL(15, 4),
|
|
p_is_win BOOLEAN
|
|
)
|
|
RETURNS VOID AS $$
|
|
DECLARE
|
|
v_alloc investment.agent_allocations%ROWTYPE;
|
|
v_tx_type investment.allocation_tx_type;
|
|
BEGIN
|
|
SELECT * INTO v_alloc
|
|
FROM investment.agent_allocations
|
|
WHERE id = p_allocation_id
|
|
FOR UPDATE;
|
|
|
|
v_tx_type := CASE WHEN p_pnl >= 0 THEN 'PROFIT_REALIZED' ELSE 'LOSS_REALIZED' END;
|
|
|
|
-- Record transaction
|
|
INSERT INTO investment.allocation_transactions (
|
|
allocation_id, tenant_id, type,
|
|
amount, balance_before, balance_after,
|
|
trade_id, trade_symbol, trade_pnl
|
|
) VALUES (
|
|
p_allocation_id, v_alloc.tenant_id, v_tx_type,
|
|
p_pnl, v_alloc.current_amount, v_alloc.current_amount + p_pnl,
|
|
p_trade_id, p_symbol, p_pnl
|
|
);
|
|
|
|
-- Update allocation
|
|
UPDATE investment.agent_allocations
|
|
SET current_amount = current_amount + p_pnl,
|
|
total_profit = CASE WHEN p_pnl > 0 THEN total_profit + p_pnl ELSE total_profit END,
|
|
total_loss = CASE WHEN p_pnl < 0 THEN total_loss + ABS(p_pnl) ELSE total_loss END,
|
|
total_trades = total_trades + 1,
|
|
winning_trades = CASE WHEN p_is_win THEN winning_trades + 1 ELSE winning_trades END,
|
|
losing_trades = CASE WHEN NOT p_is_win THEN losing_trades + 1 ELSE losing_trades END,
|
|
win_rate = CASE
|
|
WHEN total_trades > 0 THEN
|
|
(winning_trades + CASE WHEN p_is_win THEN 1 ELSE 0 END)::DECIMAL * 100 /
|
|
(total_trades + 1)
|
|
ELSE 0
|
|
END,
|
|
roi_percentage = CASE
|
|
WHEN total_deposited > 0 THEN
|
|
((current_amount + p_pnl - total_deposited + total_withdrawn) / total_deposited) * 100
|
|
ELSE 0
|
|
END,
|
|
last_trade_at = NOW()
|
|
WHERE id = p_allocation_id;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
-- RLS
|
|
ALTER TABLE investment.agent_allocations ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE investment.allocation_transactions ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE investment.profit_distributions ENABLE ROW LEVEL SECURITY;
|
|
ALTER TABLE investment.agent_configs ENABLE ROW LEVEL SECURITY;
|
|
|
|
CREATE POLICY alloc_tenant ON investment.agent_allocations
|
|
FOR ALL
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
|
|
|
|
CREATE POLICY alloc_tx_tenant ON investment.allocation_transactions
|
|
FOR ALL
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
|
|
|
|
CREATE POLICY profit_tenant ON investment.profit_distributions
|
|
FOR ALL
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
|
|
|
|
CREATE POLICY config_tenant ON investment.agent_configs
|
|
FOR ALL
|
|
USING (tenant_id = current_setting('app.current_tenant_id', true)::UUID);
|
|
|
|
-- Grants
|
|
GRANT SELECT, INSERT, UPDATE ON investment.agent_allocations TO trading_app;
|
|
GRANT SELECT, INSERT ON investment.allocation_transactions TO trading_app;
|
|
GRANT SELECT, INSERT, UPDATE ON investment.profit_distributions TO trading_app;
|
|
GRANT SELECT, UPDATE ON investment.agent_configs TO trading_app;
|
|
GRANT SELECT ON investment.agent_allocations TO trading_readonly;
|
|
GRANT SELECT ON investment.allocation_transactions TO trading_readonly;
|
|
GRANT SELECT ON investment.profit_distributions TO trading_readonly;
|
|
GRANT SELECT ON investment.agent_configs TO trading_readonly;
|