Rangefinder-funksjonalitet fantes til nå kun for GolfAPI-importerte personlige baner. Offisielle teeoff-koblede baner (org-turneringer OG frittstående runder spilt på en ekte teeoff-bane) hadde aldri noen koordinatkilde. Ny migrasjon 079: delte domener (course_poi_type/ location/side) for å unngå duplisert CHECK-vedlikehold på tvers av tabeller, ny global tabell teeoff_course_coordinate. Ny delt modul app/target_points.py + resolve_match_course_key() i hole_history.py (tredje søster til de to eksisterende bane-bro- funksjonene) -- alle tre kallesteder (frittstående runder, individuell org-turnering, lag-matchplay) bruker nå samme CourseKey-abstraksjon. rounds.py sitt eksisterende endepunkt refaktorert til samme mønster -- sideeffekt: frittstående runder på en ekte teeoff-bane får nå også rangefinder (var alltid tom liste før). Ny skrive-vei i courses.py (PUT/GET .../coordinates) -- generell, gjenbrukbar mulighet for å legge inn koordinater på enhver offisiell bane, ikke en engangsfiks. HoleTargetDistance generalisert (roundId -> baseUrl) og wiret inn i begge org-turnering-scoringsflytene. 11 nye tester (106/106 backend totalt), full scratch-verifisert ende-til-ende i nettleser i alle tre flyter inkl. lys/mørk og selvskjuling, regresjonssjekk av eksisterende GolfAPI-rangefinder bekreftet uendret oppførsel. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
76 lines
3.9 KiB
SQL
76 lines
3.9 KiB
SQL
-- =====================================================================
|
|
-- TeeCup — migrasjon 079
|
|
-- Rangefinder-koordinater for OFFISIELLE (TeeOff-koblede) baner
|
|
-- =====================================================================
|
|
-- Frem til nå har rangefinder-koordinater (golfapi_course_coordinate,
|
|
-- 065/067/078) KUN eksistert for GolfAPI-importerte baner. Offisielle
|
|
-- baner (course.source = 'official', koblet til den ekte teeoff-
|
|
-- databasen via course.external_course_ref = "{facility_slug}:
|
|
-- {teeoff_course_id}") har ALDRI hatt noen koordinatkilde -- verken for
|
|
-- org-turneringer eller for frittstående runder spilt på en ekte
|
|
-- teeoff-bane (round.course_source = 'teeoff'). Konkret anledning:
|
|
-- bruker ba om at Tjøme Golfklubb sin OFFISIELLE bane (brukt av
|
|
-- organisasjonen "Tjøme Gents") skal få samme feltbefarte koordinater
|
|
-- som nettopp ble lagt inn på Erol sin PERSONLIGE GolfAPI-bane for
|
|
-- Tjøme -- og at dette skal være en generell, gjenbrukbar mulighet for
|
|
-- ALLE offisielle baner fremover, ikke en engangsfiks.
|
|
--
|
|
-- DEL 1 -- delte domener for poi_type/location/side_fairway. To runder
|
|
-- på rad (067: rock/layup, 078: landmark) måtte hver for seg utvide
|
|
-- DEN SAMME CHECK-constraint-listen. Å innføre en ny tabell med en
|
|
-- IDENTISK, dupliserende CHECK-liste ville gjort dette vedlikeholds-
|
|
-- problemet permanent (to steder å huske å endre, garantert å skli).
|
|
-- Domenene gir én kilde til sannhet -- fremtidige utvidelser endrer
|
|
-- domenet ett sted, brukt av begge tabeller.
|
|
--
|
|
-- DEL 2 -- teeoff_course_coordinate, samme kolonneform som
|
|
-- golfapi_course_coordinate, men nøkkel er course.external_course_ref
|
|
-- (tekst, IKKE en FK -- speiler at external_course_ref selv er en myk
|
|
-- referanse, ingen global "teeoff_course"-tabell finnes å FK-e mot).
|
|
-- GLOBAL (ikke org-scopet, ingen RLS) -- samme begrunnelse som
|
|
-- golfapi_course_coordinate: flere organisasjoner kan importere samme
|
|
-- fysiske bane fra teeoff hver sin course-rad, koordinatene skal deles,
|
|
-- ikke registreres på nytt per organisasjon.
|
|
-- =====================================================================
|
|
|
|
\set ON_ERROR_STOP on
|
|
|
|
-- --- Del 1: delte domener -------------------------------------------
|
|
|
|
CREATE DOMAIN course_poi_type AS text CHECK (VALUE IN (
|
|
'green', 'green_bunker', 'fairway_bunker', 'water',
|
|
'trees', 'marker_100', 'marker_150', 'marker_200',
|
|
'dogleg', 'road', 'tee_front', 'tee_back',
|
|
'rock', 'layup', 'landmark'
|
|
));
|
|
|
|
CREATE DOMAIN course_poi_location AS text CHECK (VALUE IN ('front', 'middle', 'back'));
|
|
|
|
CREATE DOMAIN course_poi_side AS text CHECK (VALUE IN ('left', 'center', 'right'));
|
|
|
|
ALTER TABLE golfapi_course_coordinate
|
|
DROP CONSTRAINT golfapi_course_coordinate_poi_type_check,
|
|
DROP CONSTRAINT golfapi_course_coordinate_location_check,
|
|
DROP CONSTRAINT golfapi_course_coordinate_side_fairway_check;
|
|
|
|
ALTER TABLE golfapi_course_coordinate
|
|
ALTER COLUMN poi_type TYPE course_poi_type USING poi_type::text::course_poi_type,
|
|
ALTER COLUMN location TYPE course_poi_location USING location::text::course_poi_location,
|
|
ALTER COLUMN side_fairway TYPE course_poi_side USING side_fairway::text::course_poi_side;
|
|
|
|
-- --- Del 2: teeoff_course_coordinate ---------------------------------
|
|
|
|
CREATE TABLE teeoff_course_coordinate (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
external_course_ref text NOT NULL,
|
|
hole_number smallint NOT NULL CHECK (hole_number >= 1 AND hole_number <= 18),
|
|
poi_type course_poi_type NOT NULL,
|
|
location course_poi_location,
|
|
side_fairway course_poi_side,
|
|
latitude double precision NOT NULL CHECK (latitude >= -90 AND latitude <= 90),
|
|
longitude double precision NOT NULL CHECK (longitude >= -180 AND longitude <= 180)
|
|
);
|
|
|
|
CREATE INDEX ON teeoff_course_coordinate (external_course_ref, hole_number);
|
|
|
|
GRANT SELECT, INSERT, UPDATE, DELETE ON teeoff_course_coordinate TO teecup_app;
|