teecup/091_tournament_round_shot.sql
Erol Haagenrud 885dcac4e5 Slag-for-slag GPS-avstandsmåling for org-turneringer (ADR-103)
Ny tournament_round_shot-tabell (org-scopet RLS, FK-et til
tournament_round_participant + hole_number siden tournament_round_hole
kanskje ikke finnes ennå). ShotMeasurementSheet/MapPointPicker gjenbrukt
uendret; ShotMeasurementEntry generalisert fra en lokal round-detail.tsx-
funksjon til en delt, URL-parameterisert komponent. Deling går til den
rundespesifikke kommentartråden (ADR-102) i stedet for Banter Board.
Autorisasjon speiler update_hole (self/org-admin), strengere enn ADR-102s
kommentar-nivå.

Migrasjon 091 IKKE kjørt mot ekte teecup_db ennå -- venter på
brukerbekreftelse før utrulling.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-22 07:16:14 +02:00

75 lines
4.2 KiB
SQL

-- =====================================================================
-- TeeCup — Slag-for-slag GPS-avstandsmåling for org-turneringer,
-- migrasjon 091 (ADR-103). Speiler 060_round_shot.sql/
-- 061_round_shot_end_method.sql (ADR-048, frittstående runder)
-- strukturelt, men org-scopet (RLS) og med en annen eierskaps-nøkkel.
--
-- Eierskap: FK direkte til (organization_id, tournament_round_
-- participant_id) + hole_number -- IKKE tournament_round_hole_id.
-- `tournament_round_hole` opprettes (ulikt frittstående round_hole,
-- som pre-oppretter alle 18 ved rundestart) FØRST ved første
-- score-innsending (update_hole sin INSERT ... ON CONFLICT,
-- individual_tournaments.py) -- en spiller skal kunne måle et slag
-- FØR de fullfører hullets score, så en FK mot en hull-rad som kanskje
-- ikke finnes ennå ville vært feil. Samme LEFT JOIN-tolerante mønster
-- som get_tournament_round_hole_target_points/list_round_participant_
-- holes allerede bruker for nøyaktig dette problemet.
--
-- Turneringsmodellen har ALDRI en side/lag-XOR (kun individuelt) --
-- ingen tilsvarende round_side-gren trengs her, ulikt round_shot.
--
-- Koordinater: samme rene double precision lat/lng-par som round_shot
-- (ADR-048 Beslutning D) -- ingen PostGIS.
-- =====================================================================
\set ON_ERROR_STOP on
CREATE TABLE tournament_round_shot (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
organization_id uuid NOT NULL,
tournament_round_participant_id uuid NOT NULL,
hole_number smallint NOT NULL CHECK (hole_number BETWEEN 1 AND 18),
-- Hvem som MÅLTE slaget -- ikke nødvendigvis samme som deltakeren selv,
-- samme "en lenket medspiller/org-admin kan føre" som update_hole.
recorded_by_user_id uuid NOT NULL REFERENCES app_user(id),
-- Eksplisitt, hull-tolerant rekkefølge (IKKE ORDER BY captured_at) --
-- samme begrunnelse som round_shot.shot_number.
shot_number integer NOT NULL CHECK (shot_number > 0),
club text NOT NULL CHECK (char_length(club) <= 50),
distance_meters numeric(6,1) NOT NULL CHECK (distance_meters > 0 AND distance_meters < 500),
start_method text NOT NULL CHECK (start_method IN ('gps', 'map_tap')),
start_lat double precision NOT NULL CHECK (start_lat BETWEEN -90 AND 90),
start_lng double precision NOT NULL CHECK (start_lng BETWEEN -180 AND 180),
end_method text NOT NULL CHECK (end_method IN ('gps', 'map_tap')) DEFAULT 'gps',
end_lat double precision NOT NULL CHECK (end_lat BETWEEN -90 AND 90),
end_lng double precision NOT NULL CHECK (end_lng BETWEEN -180 AND 180),
-- Deling til den rundespesifikke kommentartråden (ADR-102) -- lenke,
-- ikke bare et bool-flagg, samme prinsipp som round_shot.
shared_tournament_round_message_id uuid REFERENCES tournament_round_message(id) ON DELETE SET NULL,
captured_at timestamptz NOT NULL DEFAULT now(),
FOREIGN KEY (organization_id, tournament_round_participant_id)
REFERENCES tournament_round_participant(organization_id, id) ON DELETE CASCADE,
UNIQUE (tournament_round_participant_id, hole_number, shot_number)
);
CREATE INDEX ON tournament_round_shot (organization_id, tournament_round_participant_id, hole_number, shot_number);
DO $$
BEGIN
ALTER TABLE tournament_round_shot ENABLE ROW LEVEL SECURITY;
ALTER TABLE tournament_round_shot FORCE ROW LEVEL SECURITY;
CREATE POLICY org_isolation ON tournament_round_shot
USING (organization_id = current_setting('app.current_org', true)::uuid)
WITH CHECK (organization_id = current_setting('app.current_org', true)::uuid);
END $$;
-- Samme "slett og opprett på nytt, aldri rediger"-prinsipp som round_shot
-- -- ett smalt UPDATE-unntak for delings-lenken.
GRANT SELECT, INSERT, DELETE ON tournament_round_shot TO teecup_app;
GRANT UPDATE (shared_tournament_round_message_id) ON tournament_round_shot TO teecup_app;