-- ===================================================================== -- TeeCup — migrasjon 003 -- Scoring-modus (ADR-012), blind draw (ADR-013), to-lags-format (ADR-011) -- ===================================================================== -- Kjøres etter 001 (skjema) og 002 (roller). Idempotent der det er lett å få til. -- ===================================================================== \set ON_ERROR_STOP on -- --------------------------------------------------------------------- -- 1. Scoring-modus per økt (ADR-012) -- --------------------------------------------------------------------- -- 'stroke' : spillere taster slag per hull -> hole_score. Motoren utleder -- netto og hull-resultat. -- 'hole_result' : registrer bare hvem som vant hullet -> match_hole_result. ALTER TABLE session ADD COLUMN scoring_mode text NOT NULL DEFAULT 'stroke' CHECK (scoring_mode IN ('stroke', 'hole_result')); -- --------------------------------------------------------------------- -- 2. Forenklet scoreføring: matchresultat per hull (ADR-012) -- --------------------------------------------------------------------- -- Brukes når session.scoring_mode = 'hole_result'. winning_side NULL = delt hull. -- compute_match_state i motoren mates fra enten hole_score (stroke) eller denne. CREATE TABLE match_hole_result ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), organization_id uuid NOT NULL, match_id uuid NOT NULL, hole_number smallint NOT NULL CHECK (hole_number BETWEEN 1 AND 18), winning_side team_side, -- NULL = delt (halved) created_at timestamptz NOT NULL DEFAULT now(), updated_at timestamptz NOT NULL DEFAULT now(), FOREIGN KEY (organization_id, match_id) REFERENCES match(organization_id, id) ON DELETE CASCADE, UNIQUE (match_id, hole_number) ); CREATE INDEX ON match_hole_result (organization_id, match_id); CREATE TRIGGER trg_match_hole_result_updated BEFORE UPDATE ON match_hole_result FOR EACH ROW EXECUTE FUNCTION set_updated_at(); -- --------------------------------------------------------------------- -- 3. Blind draw: lås per lag per økt (ADR-013) -- --------------------------------------------------------------------- -- En økt er "avslørt" når det finnes en lineup_lock for BEGGE lag. Appen skjuler -- motstanderens match_participant til da, og hindrer endring av egen oppstilling -- etter lås. (Finkornet synlighet i app-laget, ikke RLS — begge lag samme org.) CREATE TABLE lineup_lock ( id uuid PRIMARY KEY DEFAULT gen_random_uuid(), organization_id uuid NOT NULL, session_id uuid NOT NULL, team_id uuid NOT NULL, locked_at timestamptz NOT NULL DEFAULT now(), locked_by uuid REFERENCES app_user(id) ON DELETE SET NULL, FOREIGN KEY (organization_id, session_id) REFERENCES session(organization_id, id) ON DELETE CASCADE, FOREIGN KEY (organization_id, team_id) REFERENCES team(organization_id, id) ON DELETE CASCADE, UNIQUE (session_id, team_id) -- ett lås per lag per økt ); CREATE INDEX ON lineup_lock (organization_id, session_id); -- --------------------------------------------------------------------- -- 4. RLS for de nye tabellene (samme org-isolasjon som resten, ADR-003) -- --------------------------------------------------------------------- DO $$ DECLARE t text; BEGIN FOREACH t IN ARRAY ARRAY['match_hole_result', 'lineup_lock'] LOOP EXECUTE format('ALTER TABLE %I ENABLE ROW LEVEL SECURITY;', t); EXECUTE format('ALTER TABLE %I FORCE ROW LEVEL SECURITY;', t); EXECUTE format($p$ CREATE POLICY org_isolation ON %I USING (organization_id = current_setting('app.current_org', true)::uuid) WITH CHECK (organization_id = current_setting('app.current_org', true)::uuid); $p$, t); END LOOP; END $$; -- Grants til runtime-rollen (den eier ikke tabellene, så den trenger eksplisitt DML). GRANT SELECT, INSERT, UPDATE, DELETE ON match_hole_result TO teecup_app; GRANT SELECT, INSERT, UPDATE, DELETE ON lineup_lock TO teecup_app; -- --------------------------------------------------------------------- -- 5. To-lags-format (ADR-011) -- --------------------------------------------------------------------- -- MERK: "nøyaktig to lag per turnering" håndheves i app-laget ved -- turneringsoppsett, ikke som DB-trigger (holder match-modellen generell slik at -- flere lag / knockout kan komme senere uten dataomskriving). Ingen skjemaendring -- her — dette er kun en påminnelse om regelen.