CREATE SEQUENCE entity_id START 1; CREATE TABLE school ( id bigint PRIMARY KEY, school_key uuid NOT NULL UNIQUE, name text NOT NULL, revision bigint NOT NULL DEFAULT 0 CHECK (revision >= 0) ); CREATE TABLE dancer ( school_id bigint NOT NULL REFERENCES school ON DELETE CASCADE, id bigint NOT NULL, name text NOT NULL, birth_date date NOT NULL, PRIMARY KEY (school_id, id) ); CREATE TABLE coach ( school_id bigint NOT NULL REFERENCES school ON DELETE CASCADE, id bigint NOT NULL, name text NOT NULL, dancer_id bigint, PRIMARY KEY (school_id, id), FOREIGN KEY (school_id, dancer_id) REFERENCES dancer DEFERRABLE INITIALLY DEFERRED ); CREATE TABLE dance_group ( school_id bigint NOT NULL REFERENCES school ON DELETE CASCADE, id bigint NOT NULL, category text NOT NULL, group_type text NOT NULL, start_age integer NOT NULL CHECK (start_age >= 0), end_age integer NOT NULL CHECK (end_age >= start_age), coach_id bigint, PRIMARY KEY (school_id, id), FOREIGN KEY (school_id, coach_id) REFERENCES coach DEFERRABLE INITIALLY DEFERRED ); CREATE TABLE group_style ( school_id bigint NOT NULL, group_id bigint NOT NULL, style text NOT NULL, PRIMARY KEY (school_id, group_id, style), FOREIGN KEY (school_id, group_id) REFERENCES dance_group ON DELETE CASCADE ); CREATE TABLE group_dancer ( school_id bigint NOT NULL, group_id bigint NOT NULL, dancer_id bigint NOT NULL, PRIMARY KEY (school_id, group_id, dancer_id), FOREIGN KEY (school_id, group_id) REFERENCES dance_group ON DELETE CASCADE, FOREIGN KEY (school_id, dancer_id) REFERENCES dancer DEFERRABLE INITIALLY DEFERRED ); CREATE TABLE show ( school_id bigint NOT NULL REFERENCES school ON DELETE CASCADE, id bigint NOT NULL, name text NOT NULL, preferred_day_parts integer NOT NULL CHECK (preferred_day_parts BETWEEN 1 AND 6), finalized boolean NOT NULL, PRIMARY KEY (school_id, id) ); CREATE TABLE show_appearance ( school_id bigint NOT NULL, show_id bigint NOT NULL, group_type text NOT NULL, appearances integer NOT NULL CHECK (appearances >= 0), PRIMARY KEY (school_id, show_id, group_type), FOREIGN KEY (school_id, show_id) REFERENCES show ON DELETE CASCADE ); CREATE TABLE day_part ( school_id bigint NOT NULL, show_id bigint NOT NULL, position integer NOT NULL CHECK (position >= 0), day date NOT NULL, part_type text NOT NULL, PRIMARY KEY (school_id, show_id, position), UNIQUE (school_id, show_id, day, part_type), FOREIGN KEY (school_id, show_id) REFERENCES show ON DELETE CASCADE ); CREATE TABLE assignment ( school_id bigint NOT NULL, show_id bigint NOT NULL, part_position integer NOT NULL, position integer NOT NULL CHECK (position >= 0), group_id bigint NOT NULL, PRIMARY KEY (school_id, show_id, part_position, position), FOREIGN KEY (school_id, show_id, part_position) REFERENCES day_part ON DELETE CASCADE, FOREIGN KEY (school_id, group_id) REFERENCES dance_group DEFERRABLE INITIALLY DEFERRED ); CREATE TABLE scheduling_run ( school_id bigint NOT NULL REFERENCES school ON DELETE CASCADE, show_id bigint NOT NULL, run_id uuid NOT NULL UNIQUE, show_name text NOT NULL, started_at timestamptz NOT NULL, finished_at timestamptz, state text NOT NULL CHECK (state IN ('RUNNING','OPTIMAL','VALID','STALE','INVALID_INPUT','INFEASIBLE','NO_SOLUTION','SOLVER_FAILED','INTERRUPTED')), phase text NOT NULL CHECK (phase IN ('PREPARING','ATTENDANCE','SPREAD','VARIETY')), feasible boolean NOT NULL, message text NOT NULL, attendance_excess bigint, performance_spread integer, variety_penalty bigint, PRIMARY KEY (school_id, show_id), FOREIGN KEY (school_id, show_id) REFERENCES show DEFERRABLE INITIALLY DEFERRED, CHECK ((state = 'RUNNING') = (finished_at IS NULL)), CHECK ((attendance_excess IS NULL AND performance_spread IS NULL AND variety_penalty IS NULL) OR (attendance_excess IS NOT NULL AND performance_spread IS NOT NULL AND variety_penalty IS NOT NULL)) );