-- TimeTracker Database Initialization Script -- This script runs when the PostgreSQL container starts for the first time -- Create extensions if they don't exist CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; -- Create the database schema CREATE TABLE IF NOT EXISTS users ( id SERIAL PRIMARY KEY, username VARCHAR(50) UNIQUE NOT NULL, email VARCHAR(100) UNIQUE, password_hash VARCHAR(255) NOT NULL, is_active BOOLEAN DEFAULT true, is_admin BOOLEAN DEFAULT false, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE IF NOT EXISTS projects ( id SERIAL PRIMARY KEY, name VARCHAR(100) NOT NULL, description TEXT, color VARCHAR(7) DEFAULT '#007bff', is_active BOOLEAN DEFAULT true, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE IF NOT EXISTS tasks ( id SERIAL PRIMARY KEY, name VARCHAR(200) NOT NULL, description TEXT, project_id INTEGER REFERENCES projects(id) ON DELETE CASCADE, is_active BOOLEAN DEFAULT true, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE IF NOT EXISTS time_entries ( id SERIAL PRIMARY KEY, user_id INTEGER REFERENCES users(id) ON DELETE CASCADE, task_id INTEGER REFERENCES tasks(id) ON DELETE CASCADE, start_time TIMESTAMP NOT NULL, end_time TIMESTAMP, duration_minutes INTEGER, description TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE IF NOT EXISTS settings ( id SERIAL PRIMARY KEY, key VARCHAR(100) UNIQUE NOT NULL, value TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); -- Create indexes for better performance CREATE INDEX IF NOT EXISTS idx_time_entries_user_id ON time_entries(user_id); CREATE INDEX IF NOT EXISTS idx_time_entries_task_id ON time_entries(task_id); CREATE INDEX IF NOT EXISTS idx_time_entries_start_time ON time_entries(start_time); CREATE INDEX IF NOT EXISTS idx_tasks_project_id ON tasks(project_id); -- Insert default admin user (password: admin) INSERT INTO users (username, email, password_hash, is_admin) VALUES ('admin', 'admin@timetracker.local', '$2b$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/LewdBPj/RK.s5uO.G', true) ON CONFLICT (username) DO NOTHING; -- Insert default project INSERT INTO projects (name, description, color) VALUES ('General', 'Default project for general tasks', '#007bff') ON CONFLICT DO NOTHING; -- Insert default task INSERT INTO tasks (name, description, project_id) VALUES ('General Task', 'Default task for time tracking', 1) ON CONFLICT DO NOTHING; -- Insert default settings INSERT INTO settings (key, value) VALUES ('currency', 'EUR'), ('timezone', 'Europe/Brussels'), ('rounding_minutes', '1'), ('single_active_timer', 'true'), ('allow_self_register', 'true'), ('idle_timeout_minutes', '30') ON CONFLICT (key) DO NOTHING; -- Create function to update updated_at timestamp CREATE OR REPLACE FUNCTION update_updated_at_column() RETURNS TRIGGER AS $$ BEGIN NEW.updated_at = CURRENT_TIMESTAMP; RETURN NEW; END; $$ language 'plpgsql'; -- Create triggers to automatically update updated_at CREATE TRIGGER update_users_updated_at BEFORE UPDATE ON users FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_projects_updated_at BEFORE UPDATE ON projects FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_tasks_updated_at BEFORE UPDATE ON tasks FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_time_entries_updated_at BEFORE UPDATE ON time_entries FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_settings_updated_at BEFORE UPDATE ON settings FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); -- Grant permissions GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO timetracker; GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO timetracker; GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public TO timetracker;