-- EnakGame events, also called campaigns (docs/rfc-enakgame.md §5.5, D6): a period in -- which some games pay more, the extra paid by the event's own budget. CREATE TABLE game_events ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), organization_id UUID NOT NULL, name VARCHAR(255) NOT NULL, slug VARCHAR(100) NOT NULL, description TEXT, banner_url VARCHAR(500), start_at TIMESTAMP WITH TIME ZONE NOT NULL, end_at TIMESTAMP WITH TIME ZONE NOT NULL, -- Shown with the dates; start_at and end_at are instants already. timezone VARCHAR(50) NOT NULL DEFAULT 'Asia/Jakarta', status VARCHAR(20) NOT NULL DEFAULT 'DRAFT', -- Higher goes first; when the reward cap cuts, the lowest goes first. priority INT NOT NULL DEFAULT 0, -- Applied to the base reward: 2.00 adds the base once more. multiplier NUMERIC(5,2), -- Added on top, per completed session. bonus BIGINT, -- Pays what this event adds. A budget of scope EVENT, checked by the processor. budget_id UUID NOT NULL REFERENCES game_budgets(id), -- EnakCoin this event may add over its whole run (PRD §35 Event Limit). reward_limit BIGINT, -- EnakCoin this event may add for one customer per day. user_daily_limit BIGINT, created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(), CONSTRAINT uq_game_events_slug UNIQUE (organization_id, slug), CONSTRAINT chk_game_events_period CHECK (end_at > start_at), CONSTRAINT chk_game_events_status CHECK (status IN ('DRAFT', 'ACTIVE', 'ENDED', 'CANCELLED')), CONSTRAINT chk_game_events_multiplier CHECK (multiplier IS NULL OR multiplier > 0), CONSTRAINT chk_game_events_bonus CHECK (bonus IS NULL OR bonus > 0), CONSTRAINT chk_game_events_reward_limit CHECK (reward_limit IS NULL OR reward_limit > 0), CONSTRAINT chk_game_events_user_daily_limit CHECK (user_daily_limit IS NULL OR user_daily_limit > 0) ); CREATE INDEX idx_game_events_org_active ON game_events(organization_id, start_at, end_at) WHERE status = 'ACTIVE'; CREATE TABLE game_event_games ( event_id UUID NOT NULL REFERENCES game_events(id) ON DELETE CASCADE, game_id UUID NOT NULL REFERENCES games(id) ON DELETE RESTRICT, PRIMARY KEY (event_id, game_id) ); CREATE INDEX idx_game_event_games_game ON game_event_games(game_id);