-- Kích hoạt extension PostGIS để xử lý tọa độ địa lý CREATE EXTENSION IF NOT EXISTS postgis; -- 3.1. Users CREATE TABLE users ( id SERIAL PRIMARY KEY, email VARCHAR(255) UNIQUE NOT NULL, password_hash TEXT NOT NULL, name VARCHAR(100), avatar TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- 3.2. Tours & Members CREATE TABLE tours ( id SERIAL PRIMARY KEY, title VARCHAR(255) NOT NULL, start_date DATE, end_date DATE, creator_id INTEGER REFERENCES users(id), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TYPE member_role AS ENUM ('OWNER', 'EDITOR', 'MEMBER_PLAN_ONLY', 'MEMBER_PHOTO_ONLY', 'VIEWER_EXTERNAL'); CREATE TABLE tour_members ( tour_id INTEGER REFERENCES tours(id), user_id INTEGER REFERENCES users(id), role member_role DEFAULT 'MEMBER_PLAN_ONLY', PRIMARY KEY (tour_id, user_id) ); -- 3.3. Itinerary & Map CREATE TABLE legs ( id SERIAL PRIMARY KEY, tour_id INTEGER REFERENCES tours(id), sequence_number INTEGER NOT NULL, notes TEXT ); CREATE TABLE places ( id SERIAL PRIMARY KEY, leg_id INTEGER REFERENCES legs(id), name VARCHAR(255), address TEXT, geom GEOMETRY(Point, 4326), -- PostGIS coordinates sequence_in_leg INTEGER, arrival_time TIMESTAMP, departure_time TIMESTAMP ); -- 3.4. Expenses CREATE TYPE expense_category AS ENUM ('LODGING', 'DINING', 'TRANSPORT', 'OTHER'); CREATE TABLE expenses ( id SERIAL PRIMARY KEY, leg_id INTEGER REFERENCES legs(id), place_id INTEGER REFERENCES places(id), category expense_category, amount DECIMAL(15, 2) NOT NULL, currency VARCHAR(10) DEFAULT 'VND', description TEXT ); -- 3.5. Tasks CREATE TYPE trigger_type AS ENUM ('AUTO_BY_TIME', 'MANUAL_BY_USER'); CREATE TABLE tasks ( id SERIAL PRIMARY KEY, tour_id INTEGER REFERENCES tours(id), leg_id INTEGER REFERENCES legs(id), title VARCHAR(255), planned_timestamp TIMESTAMP, is_completed BOOLEAN DEFAULT FALSE, completed_at TIMESTAMP, trigger_type trigger_type DEFAULT 'MANUAL_BY_USER' );