CREATE TABLE IF NOT EXISTS virtual_games ( id BIGSERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, provider VARCHAR(255) NOT NULL, category VARCHAR(100), min_bet NUMERIC(10, 2) NOT NULL, max_bet NUMERIC(10, 2) NOT NULL, volatility VARCHAR(50), is_active BOOLEAN NOT NULL DEFAULT TRUE, rtp NUMERIC(5, 2) CHECK (rtp >= 0 AND rtp <= 100), is_featured BOOLEAN NOT NULL DEFAULT FALSE, popularity_score INT DEFAULT 0, thumbnail_url TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMPTZ ); CREATE TABLE virtual_game_sessions ( id BIGSERIAL PRIMARY KEY, user_id BIGINT NOT NULL REFERENCES users(id), game_id VARCHAR(50) NOT NULL, session_token VARCHAR(255) NOT NULL UNIQUE, currency VARCHAR(3) NOT NULL, status VARCHAR(20) NOT NULL DEFAULT 'ACTIVE', -- ACTIVE, COMPLETED, FAILED created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, expires_at TIMESTAMP WITH TIME ZONE NOT NULL ); CREATE TABLE virtual_game_transactions ( id BIGSERIAL PRIMARY KEY, session_id BIGINT NOT NULL REFERENCES virtual_game_sessions(id), user_id BIGINT NOT NULL REFERENCES users(id), company_id BIGINT, provider VARCHAR(100), game_id VARCHAR(100), wallet_id BIGINT NOT NULL REFERENCES wallets(id), transaction_type VARCHAR(20) NOT NULL, amount BIGINT NOT NULL, currency VARCHAR(3) NOT NULL, external_transaction_id VARCHAR(100) NOT NULL UNIQUE, -- PopOK transaction ID status VARCHAR(20) NOT NULL DEFAULT 'PENDING', -- PENDING, COMPLETED, FAILED created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE virtual_game_histories ( id BIGSERIAL PRIMARY KEY, session_id VARCHAR(100), -- nullable user_id BIGINT NOT NULL, company_id BIGINT, provider VARCHAR(100), wallet_id BIGINT, -- nullable game_id BIGINT, -- nullable transaction_type VARCHAR(20) NOT NULL, -- e.g., BET, WIN, CANCEL amount BIGINT NOT NULL, -- in cents or smallest currency unit currency VARCHAR(10) NOT NULL, external_transaction_id VARCHAR(100) NOT NULL, reference_transaction_id VARCHAR(100), -- nullable, for cancel/refund status VARCHAR(20) NOT NULL DEFAULT 'COMPLETED', -- transaction status created_at TIMESTAMP NOT NULL DEFAULT NOW(), updated_at TIMESTAMP NOT NULL DEFAULT NOW() ); CREATE TABLE IF NOT EXISTS favorite_games ( id BIGSERIAL PRIMARY KEY, user_id BIGINT NOT NULL, game_id BIGINT NOT NULL, created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); -- Optional: Indexes for performance CREATE INDEX idx_virtual_game_user_id ON virtual_game_histories(user_id); CREATE INDEX idx_virtual_game_transaction_type ON virtual_game_histories(transaction_type); CREATE INDEX idx_virtual_game_game_id ON virtual_game_histories(game_id); CREATE INDEX idx_virtual_game_external_transaction_id ON virtual_game_histories(external_transaction_id); CREATE INDEX idx_virtual_game_sessions_user_id ON virtual_game_sessions(user_id); CREATE INDEX idx_virtual_game_transactions_session_id ON virtual_game_transactions(session_id); CREATE INDEX idx_virtual_game_transactions_user_id ON virtual_game_transactions(user_id); ALTER TABLE favorite_games ADD CONSTRAINT unique_user_game_favorite UNIQUE (user_id, game_id);