teecup/060_round_shot.sql
2026-08-07 22:02:56 +02:00

75 lines
4.1 KiB
SQL

-- =====================================================================
-- TeeCup — Slag-for-slag GPS-avstandsmåling, migrasjon 060 (ADR-048).
--
-- IKKE en gjenåpning av ADR-033s avvisning av fri slag-for-slag-logging
-- som DATAMODELL for hull-statistikk. Dette er en separat, valgfri
-- måle-funksjon: spilleren kan måle avstanden på ett eller flere
-- enkeltslag med GPS, uavhengig av det faste hull-statistikk-skjemaet.
-- `round_hole` sine faste felt (club_off_tee, putts, osv.) er UBERØRT.
--
-- Eierskap: round_shot henger kun av round_hole.id -- IKKE direkte av
-- round_participant_id/round_side_id. round_hole har allerede en XOR
-- mellom disse to (round_hole_owner_xor, migrasjon 031), så round_shot
-- arver eierskapet (individuell ELLER lagformat) transitivt uten å
-- duplisere XOR-logikken selv. Dette dekker BEGGE hull-typer fra v1
-- (ADR-048 Beslutning C).
--
-- Eier-mønster for øvrig: samme non-RLS plain_connection() + WHERE-
-- filtrering som resten av frittstående-runde-subsystemet (ADR-033
-- Beslutning A).
--
-- Koordinater: rene double precision lat/lng-par, IKKE PostGIS. Volum er
-- maks noen titalls rader per runde, og eneste geometriske operasjon er
-- punkt-til-punkt storsirkel-avstand (Haversine), regnet CLIENT-SIDE i
-- JS -- PostGIS ville vært en ny, tung avhengighet uten reell gevinst
-- her (ADR-048 Beslutning D).
-- =====================================================================
\set ON_ERROR_STOP on
CREATE TABLE round_shot (
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
round_hole_id uuid NOT NULL REFERENCES round_hole(id) ON DELETE CASCADE,
-- Hvem som MÅLTE slaget -- ikke nødvendigvis samme som round_hole sin
-- eier, en medspiller kan føre for flighten (samme skrive-autorisasjons-
-- modell som update_hole/side-PATCH allerede bruker).
recorded_by_user_id uuid NOT NULL REFERENCES app_user(id),
-- Eksplisitt, hull-tolerant rekkefølge (IKKE ORDER BY captured_at) --
-- lar et slag midt i sekvensen slettes uten omnummerering av resten,
-- og unngår at GPS-tidsstempel-drift/bakgrunnsthrottling noensinne
-- stille endrer rekkefølgen.
shot_number integer NOT NULL CHECK (shot_number > 0),
club text NOT NULL CHECK (char_length(club) <= 50),
-- Øvre grense 500m er en fornuftssjekk mot GPS-glitch/feiltrykk, ikke
-- en golf-regel (lengste realistiske driver ligger rundt 370m).
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_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 rundens kommentarfelt (ADR-044) -- lenke, ikke bare et
-- bool-flagg, slik at "delt" alltid reflekterer om meldingen FAKTISK
-- finnes (ON DELETE SET NULL: slettes meldingen separat i feeden,
-- forblir slaget "målt, men ikke lenger delt", ikke ugyldig).
shared_round_message_id uuid REFERENCES round_message(id) ON DELETE SET NULL,
captured_at timestamptz NOT NULL DEFAULT now(),
UNIQUE (round_hole_id, shot_number)
);
CREATE INDEX round_shot_hole_idx ON round_shot (round_hole_id, shot_number);
-- INGEN RLS -- samme plain_connection()-mønster som round_message/
-- round_hole (ADR-033 Beslutning A). Autorisasjon i app-laget.
GRANT SELECT, INSERT, DELETE ON round_shot TO teecup_app;
-- Ingen generell UPDATE-grant -- samme "slett og opprett på nytt, aldri
-- rediger"-prinsipp som round_message (et feilmålt slag slettes og måles
-- på nytt). ETT eksplisitt, smalt unntak: å knytte et allerede opprettet
-- slag til en round_message som opprettes i et eget, påfølgende
-- delings-steg (se app/routers/rounds.py, share_shot).
GRANT UPDATE (shared_round_message_id) ON round_shot TO teecup_app;