🗄️ Datenbank-Migration erstellt
This commit is contained in:
163
db/migrations/001_initial.sql
Normal file
163
db/migrations/001_initial.sql
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
-- SeCu Database Schema
|
||||||
|
-- Version: 1.0.0
|
||||||
|
|
||||||
|
-- Enable UUID extension
|
||||||
|
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||||
|
|
||||||
|
-- Organizations
|
||||||
|
CREATE TABLE IF NOT EXISTS organizations (
|
||||||
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
|
name VARCHAR(255) NOT NULL,
|
||||||
|
slug VARCHAR(100) NOT NULL UNIQUE,
|
||||||
|
settings JSONB DEFAULT '{}',
|
||||||
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Users
|
||||||
|
CREATE TABLE IF NOT EXISTS users (
|
||||||
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
|
org_id UUID NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
||||||
|
email VARCHAR(255) NOT NULL,
|
||||||
|
password_hash VARCHAR(255) NOT NULL,
|
||||||
|
role VARCHAR(20) NOT NULL CHECK (role IN ('chef', 'disponent', 'mitarbeiter')),
|
||||||
|
first_name VARCHAR(100) NOT NULL,
|
||||||
|
last_name VARCHAR(100) NOT NULL,
|
||||||
|
phone VARCHAR(50),
|
||||||
|
avatar_url TEXT,
|
||||||
|
created_by UUID REFERENCES users(id),
|
||||||
|
managed_by UUID REFERENCES users(id),
|
||||||
|
active BOOLEAN DEFAULT true,
|
||||||
|
last_login TIMESTAMP WITH TIME ZONE,
|
||||||
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||||
|
UNIQUE(org_id, email)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Refresh Tokens
|
||||||
|
CREATE TABLE IF NOT EXISTS refresh_tokens (
|
||||||
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
|
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||||
|
token_hash VARCHAR(255) NOT NULL,
|
||||||
|
expires_at TIMESTAMP WITH TIME ZONE NOT NULL,
|
||||||
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Orders (Aufträge)
|
||||||
|
CREATE TABLE IF NOT EXISTS orders (
|
||||||
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
|
org_id UUID NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
||||||
|
number SERIAL,
|
||||||
|
title VARCHAR(255) NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
location VARCHAR(255),
|
||||||
|
address TEXT,
|
||||||
|
client_name VARCHAR(255),
|
||||||
|
client_contact VARCHAR(255),
|
||||||
|
status VARCHAR(20) NOT NULL DEFAULT 'draft' CHECK (status IN ('draft', 'published', 'in_progress', 'completed', 'cancelled')),
|
||||||
|
start_time TIMESTAMP WITH TIME ZONE,
|
||||||
|
end_time TIMESTAMP WITH TIME ZONE,
|
||||||
|
required_staff INTEGER DEFAULT 1,
|
||||||
|
special_instructions TEXT,
|
||||||
|
created_by UUID REFERENCES users(id),
|
||||||
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Order Assignments (Mitarbeiter-Zuweisung)
|
||||||
|
CREATE TABLE IF NOT EXISTS order_assignments (
|
||||||
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
|
order_id UUID NOT NULL REFERENCES orders(id) ON DELETE CASCADE,
|
||||||
|
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||||
|
status VARCHAR(20) NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'confirmed', 'declined', 'completed')),
|
||||||
|
note TEXT,
|
||||||
|
confirmed_at TIMESTAMP WITH TIME ZONE,
|
||||||
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||||
|
UNIQUE(order_id, user_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Availability (Verfügbarkeit)
|
||||||
|
CREATE TABLE IF NOT EXISTS availability (
|
||||||
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
|
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||||
|
date DATE NOT NULL,
|
||||||
|
available BOOLEAN NOT NULL DEFAULT true,
|
||||||
|
time_from TIME,
|
||||||
|
time_to TIME,
|
||||||
|
note TEXT,
|
||||||
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||||
|
UNIQUE(user_id, date)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Timesheets (Stundenzettel)
|
||||||
|
CREATE TABLE IF NOT EXISTS timesheets (
|
||||||
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
|
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||||
|
order_id UUID REFERENCES orders(id) ON DELETE SET NULL,
|
||||||
|
work_date DATE NOT NULL,
|
||||||
|
start_time TIME,
|
||||||
|
end_time TIME,
|
||||||
|
hours_worked DECIMAL(5,2),
|
||||||
|
photo_url TEXT,
|
||||||
|
status VARCHAR(20) NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'approved', 'rejected')),
|
||||||
|
approved_by UUID REFERENCES users(id),
|
||||||
|
rejection_reason TEXT,
|
||||||
|
approved_at TIMESTAMP WITH TIME ZONE,
|
||||||
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Modules (für modulares System)
|
||||||
|
CREATE TABLE IF NOT EXISTS modules (
|
||||||
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
|
name VARCHAR(100) NOT NULL UNIQUE,
|
||||||
|
display_name VARCHAR(255) NOT NULL,
|
||||||
|
description TEXT,
|
||||||
|
is_core BOOLEAN DEFAULT false,
|
||||||
|
default_config JSONB DEFAULT '{}',
|
||||||
|
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Organization Modules (welche Module aktiviert)
|
||||||
|
CREATE TABLE IF NOT EXISTS organization_modules (
|
||||||
|
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||||
|
org_id UUID NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
||||||
|
module_id UUID NOT NULL REFERENCES modules(id) ON DELETE CASCADE,
|
||||||
|
enabled BOOLEAN DEFAULT true,
|
||||||
|
config JSONB DEFAULT '{}',
|
||||||
|
enabled_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||||
|
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||||
|
UNIQUE(org_id, module_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Indexes for performance
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_users_org_id ON users(org_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_users_email ON users(email);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_users_role ON users(role);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_users_managed_by ON users(managed_by);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_orders_org_id ON orders(org_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_orders_status ON orders(status);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_orders_start_time ON orders(start_time);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_order_assignments_order_id ON order_assignments(order_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_order_assignments_user_id ON order_assignments(user_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_availability_user_id ON availability(user_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_availability_date ON availability(date);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_timesheets_user_id ON timesheets(user_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_timesheets_work_date ON timesheets(work_date);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_timesheets_status ON timesheets(status);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_refresh_tokens_user_id ON refresh_tokens(user_id);
|
||||||
|
|
||||||
|
-- Seed data: Core modules
|
||||||
|
INSERT INTO modules (name, display_name, description, is_core) VALUES
|
||||||
|
('core', 'Kernfunktionen', 'Authentifizierung und Benutzerverwaltung', true),
|
||||||
|
('orders', 'Auftragsverwaltung', 'Erstellen und Verwalten von Aufträgen', true),
|
||||||
|
('availability', 'Verfügbarkeit', 'Mitarbeiter-Verfügbarkeitsplanung', false),
|
||||||
|
('timesheets', 'Stundenzettel', 'Zeiterfassung und Stundenzettel-Upload', false),
|
||||||
|
('developer', 'Entwickler-Panel', 'Fernverwaltung und Modul-Konfiguration', false)
|
||||||
|
ON CONFLICT (name) DO NOTHING;
|
||||||
|
|
||||||
|
-- Create a default demo organization
|
||||||
|
INSERT INTO organizations (name, slug) VALUES
|
||||||
|
('Demo Organisation', 'demo')
|
||||||
|
ON CONFLICT (slug) DO NOTHING;
|
||||||
Reference in New Issue
Block a user