98 lines
4.6 KiB
SQL
98 lines
4.6 KiB
SQL
-- =====================================================================
|
|
-- 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.
|