155 lines
5.6 KiB
SQL
155 lines
5.6 KiB
SQL
CREATE EXTENSION IF NOT EXISTS postgis;
|
|
CREATE EXTENSION IF NOT EXISTS pgcrypto;
|
|
|
|
CREATE TABLE IF NOT EXISTS hunt_area (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
name text NOT NULL,
|
|
description text,
|
|
geom geometry(MultiPolygon, 4326),
|
|
created_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS app_user (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
display_name text NOT NULL,
|
|
email text,
|
|
avatar_url text,
|
|
color text,
|
|
is_active boolean NOT NULL DEFAULT true,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
updated_at timestamptz
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS user_identity (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
user_id uuid NOT NULL REFERENCES app_user(id) ON DELETE CASCADE,
|
|
provider text NOT NULL,
|
|
provider_subject text NOT NULL,
|
|
email text,
|
|
email_verified boolean,
|
|
display_name text,
|
|
avatar_url text,
|
|
first_login_at timestamptz NOT NULL DEFAULT now(),
|
|
last_login_at timestamptz NOT NULL DEFAULT now(),
|
|
UNIQUE (provider, provider_subject),
|
|
CHECK (provider IN ('google', 'microsoft', 'apple'))
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS hunt (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
hunt_area_id uuid NOT NULL REFERENCES hunt_area(id),
|
|
title text NOT NULL,
|
|
description text,
|
|
starts_at timestamptz,
|
|
ends_at timestamptz,
|
|
status text NOT NULL DEFAULT 'planned',
|
|
created_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS map_point_type (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
name text NOT NULL UNIQUE,
|
|
icon text,
|
|
color text
|
|
);
|
|
|
|
INSERT INTO map_point_type (name, icon, color) VALUES
|
|
('HuntingTower', 'tower', '#F59E0B'),
|
|
('FeedingPlace', 'corn', '#84CC16'),
|
|
('Parking', 'parking', '#3B82F6'),
|
|
('MeetingPoint', 'flag', '#22C55E'),
|
|
('Observation', 'eye', '#A855F7')
|
|
ON CONFLICT (name) DO NOTHING;
|
|
|
|
CREATE TABLE IF NOT EXISTS map_point (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
hunt_area_id uuid NOT NULL REFERENCES hunt_area(id),
|
|
type_id uuid NOT NULL REFERENCES map_point_type(id),
|
|
name text NOT NULL,
|
|
description text,
|
|
geom geometry(Point, 4326) NOT NULL,
|
|
image_url text,
|
|
is_active boolean NOT NULL DEFAULT true,
|
|
created_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS map_zone (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
hunt_area_id uuid NOT NULL REFERENCES hunt_area(id),
|
|
name text NOT NULL,
|
|
zone_type text NOT NULL,
|
|
description text,
|
|
geom geometry(MultiPolygon, 4326) NOT NULL,
|
|
created_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS hunt_area_member (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
hunt_area_id uuid NOT NULL REFERENCES hunt_area(id) ON DELETE CASCADE,
|
|
user_id uuid NOT NULL REFERENCES app_user(id) ON DELETE CASCADE,
|
|
role text NOT NULL DEFAULT 'member',
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
UNIQUE (hunt_area_id, user_id)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS hunt_participant (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
hunt_id uuid NOT NULL REFERENCES hunt(id) ON DELETE CASCADE,
|
|
user_id uuid NOT NULL REFERENCES app_user(id),
|
|
role text NOT NULL DEFAULT 'hunter',
|
|
status text NOT NULL DEFAULT 'invited',
|
|
share_location boolean NOT NULL DEFAULT true,
|
|
created_at timestamptz NOT NULL DEFAULT now(),
|
|
UNIQUE (hunt_id, user_id)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS hunt_assignment (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
hunt_id uuid NOT NULL REFERENCES hunt(id) ON DELETE CASCADE,
|
|
participant_id uuid NOT NULL REFERENCES hunt_participant(id) ON DELETE CASCADE,
|
|
map_point_id uuid NOT NULL REFERENCES map_point(id),
|
|
note text,
|
|
assigned_at timestamptz NOT NULL DEFAULT now(),
|
|
UNIQUE (hunt_id, participant_id)
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS user_current_location (
|
|
participant_id uuid PRIMARY KEY REFERENCES hunt_participant(id) ON DELETE CASCADE,
|
|
geom geometry(Point, 4326) NOT NULL,
|
|
accuracy_m numeric(8,2),
|
|
speed_mps numeric(8,2),
|
|
heading_degrees numeric(6,2),
|
|
battery_percent int,
|
|
recorded_at timestamptz NOT NULL,
|
|
received_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS user_location_history (
|
|
id bigserial PRIMARY KEY,
|
|
participant_id uuid NOT NULL REFERENCES hunt_participant(id) ON DELETE CASCADE,
|
|
geom geometry(Point, 4326) NOT NULL,
|
|
accuracy_m numeric(8,2),
|
|
speed_mps numeric(8,2),
|
|
heading_degrees numeric(6,2),
|
|
battery_percent int,
|
|
recorded_at timestamptz NOT NULL,
|
|
received_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE TABLE IF NOT EXISTS hunt_message (
|
|
id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
hunt_id uuid NOT NULL REFERENCES hunt(id) ON DELETE CASCADE,
|
|
sender_participant_id uuid REFERENCES hunt_participant(id),
|
|
message text NOT NULL,
|
|
created_at timestamptz NOT NULL DEFAULT now()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_hunt_area_geom ON hunt_area USING gist (geom);
|
|
CREATE INDEX IF NOT EXISTS idx_map_point_geom ON map_point USING gist (geom);
|
|
CREATE INDEX IF NOT EXISTS idx_map_zone_geom ON map_zone USING gist (geom);
|
|
CREATE INDEX IF NOT EXISTS idx_user_current_location_geom ON user_current_location USING gist (geom);
|
|
CREATE INDEX IF NOT EXISTS idx_user_location_history_geom ON user_location_history USING gist (geom);
|
|
CREATE INDEX IF NOT EXISTS idx_user_location_history_participant_time ON user_location_history (participant_id, recorded_at DESC);
|
|
CREATE INDEX IF NOT EXISTS idx_hunt_participant_hunt ON hunt_participant (hunt_id);
|
|
CREATE INDEX IF NOT EXISTS idx_hunt_assignment_hunt ON hunt_assignment (hunt_id);
|