Files
pingu-concerts/db/init/01_initial.sql
T
kai 4035176370 - Freitext wird jetzt direkt als venue_name übertragen und somit auch ohne Suchtreffer gespeichert.
- Die Suche ist international und kombiniert lokale Ergebnisse mit Nominatim.
  - Externe IDs werden korrekt als nominatim:<Typ>:<ID> gespeichert und dedupliziert.
  - Straße, PLZ, Stadt und Land können beim Anlegen manuell ergänzt werden.
  - Im Adminbereich können Orte korrigiert, bestätigt, mit Aliasen versehen und zusammengeführt werden.
2026-08-26 10:02:52 +02:00

118 lines
3.6 KiB
SQL

CREATE TABLE users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) NOT NULL UNIQUE,
email VARCHAR(255) NOT NULL UNIQUE,
password_hash TEXT NOT NULL,
display_name VARCHAR(100),
avatar_path TEXT,
is_admin BOOLEAN NOT NULL DEFAULT FALSE,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE registration_invites (
id SERIAL PRIMARY KEY,
token_hash TEXT NOT NULL UNIQUE,
expires_at TIMESTAMP,
used_by INTEGER REFERENCES users(id),
used_at TIMESTAMP,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE sessions (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
token_hash TEXT NOT NULL UNIQUE,
expires_at TIMESTAMP NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE venues (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
street VARCHAR(255),
postal_code VARCHAR(20),
city VARCHAR(100),
country VARCHAR(100) DEFAULT 'Deutschland',
latitude DOUBLE PRECISION,
longitude DOUBLE PRECISION,
external_id VARCHAR(255),
source VARCHAR(50),
is_verified BOOLEAN NOT NULL DEFAULT FALSE,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE venue_aliases (
id SERIAL PRIMARY KEY,
venue_id INTEGER NOT NULL REFERENCES venues(id) ON DELETE CASCADE,
alias VARCHAR(255) NOT NULL,
UNIQUE (venue_id, alias)
);
CREATE TABLE concerts (
id SERIAL PRIMARY KEY,
artist VARCHAR(255) NOT NULL,
venue_id INTEGER REFERENCES venues(id) ON DELETE SET NULL,
start_datetime TIMESTAMP NOT NULL,
end_datetime TIMESTAMP,
description TEXT,
ticket_url TEXT,
ticket_price NUMERIC(10,2),
flyer_path TEXT,
created_by INTEGER REFERENCES users(id) ON DELETE SET NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE concert_comments (
id SERIAL PRIMARY KEY,
concert_id INTEGER NOT NULL REFERENCES concerts(id) ON DELETE CASCADE,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
body TEXT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE concert_photos (
id SERIAL PRIMARY KEY,
concert_id INTEGER NOT NULL REFERENCES concerts(id) ON DELETE CASCADE,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
path TEXT NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE concert_attendance (
concert_id INTEGER NOT NULL REFERENCES concerts(id) ON DELETE CASCADE,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
status VARCHAR(20) NOT NULL CHECK (
status IN ('attending', 'maybe', 'ticket_search')
),
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (concert_id, user_id)
);
CREATE TABLE user_badges (
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
badge_code VARCHAR(50) NOT NULL,
awarded_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (user_id, badge_code)
);
CREATE INDEX idx_concerts_start_datetime
ON concerts(start_datetime);
CREATE INDEX idx_venues_name
ON venues(name);
CREATE INDEX idx_venues_external_id
ON venues(external_id);
CREATE INDEX idx_venue_aliases_alias
ON venue_aliases (LOWER(alias));
CREATE INDEX idx_concert_comments_concert
ON concert_comments(concert_id, created_at);
CREATE INDEX idx_concert_photos_concert
ON concert_photos(concert_id, created_at);
CREATE INDEX idx_concert_attendance_concert
ON concert_attendance(concert_id, status);