CREATE TABLE users ( id BIGSERIAL PRIMARY KEY, first_name VARCHAR(255) NOT NULL, last_name VARCHAR(255) NOT NULL, email VARCHAR(255) UNIQUE , phone_number VARCHAR(20) UNIQUE, role VARCHAR(50) NOT NULL, password BYTEA NOT NULL, email_verified BOOLEAN NOT NULL DEFAULT FALSE, phone_verified BOOLEAN NOT NULL DEFAULT FALSE, created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMPTZ , -- suspended_at TIMESTAMPTZ NULL, -- this can be NULL if the user is not suspended suspended BOOLEAN NOT NULL DEFAULT FALSE, CHECK (email IS NOT NULL OR phone_number IS NOT NULL) ); CREATE TABLE refresh_tokens ( id BIGSERIAL PRIMARY KEY, user_id BIGINT NOT NULL, token TEXT NOT NULL UNIQUE, expires_at TIMESTAMPTZ NOT NULL, created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP NOT NULL, revoked BOOLEAN DEFAULT FALSE NOT NULL, CONSTRAINT unique_token UNIQUE (token) ); ----- CREATE TABLE otps ( id BIGSERIAL PRIMARY KEY, sent_to VARCHAR(255) NOT NULL, medium VARCHAR(50) NOT NULL, otp_for VARCHAR(50) NOT NULL, otp VARCHAR(10) NOT NULL, used BOOLEAN NOT NULL DEFAULT FALSE, used_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT CURRENT_TIMESTAMP, expires_at TIMESTAMPTZ NOT NULL ); ----------------------------------------------seed data------------------------------------------------------------- -------------------------------------- DO NOT USE IN PRODUCTION------------------------------------------------- CREATE EXTENSION IF NOT EXISTS pgcrypto; INSERT INTO users ( first_name, last_name, email, phone_number, password, role, email_verified, phone_verified, created_at, updated_at, suspended_at, suspended ) VALUES ( 'John', 'Doe', 'john.doe@example.com', NULL, crypt('password123', gen_salt('bf'))::bytea, 'customer', TRUE, FALSE, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP, NULL, FALSE ); --------------------------------------------------Bet365 Data Fetching + Event Managment------------------------------------------------ CREATE TABLE events ( id TEXT PRIMARY KEY, sport_id TEXT, match_name TEXT, home_team TEXT, away_team TEXT, home_team_id TEXT, away_team_id TEXT, home_kit_image TEXT, away_kit_image TEXT, league_id TEXT, league_name TEXT, league_cc TEXT, start_time TIMESTAMP, score TEXT, match_minute INT, timer_status TEXT, added_time INT, match_period INT, is_live BOOLEAN, status TEXT, fetched_at TIMESTAMP DEFAULT now() ); CREATE TABLE odds ( id SERIAL PRIMARY KEY, event_id TEXT, -- Parsed from "FI" (Bet365 Event ID). Nullable in case of failures. market_type TEXT NOT NULL, -- E.g., 'asian_handicap', 'goal_line', 'both_teams_to_score' header TEXT, -- E.g., '1', '2', 'Over', 'Under', 'Draw', 'Yes', 'No' name TEXT, -- Bet name like "2.5", "Over 2.5 & Yes", etc. odds_value DOUBLE PRECISION, -- The numeric odds (e.g., 1.920) handicap TEXT, -- Handicap value like "-0.5", "0.0, +0.5" section TEXT NOT NULL, -- Odds section: 'asian_lines', 'goals', etc. category TEXT, -- Market category (e.g., 'sp') market_id TEXT, -- Market ID from the API (e.g., "938", "50138") fetched_at TIMESTAMP DEFAULT now(), -- When this record was fetched source TEXT DEFAULT 'b365api', -- Source identifier is_active BOOLEAN DEFAULT true, -- Optional deactivation flag raw_event_id TEXT -- Original/failed event ID if event_id is nil or invalid );