feat: Datenbank-Schema & ER-Diagramm
📊 Schema (schema.sql): - organizations (Multi-Tenancy) - users (mit Rollen) - contacts (mit DSGVO Felder) - companies - pipelines (JSONB stages) - deals - activities - audit_logs (DSGVO) - refresh_tokens 📈 ER-Diagramm (Mermaid) 🌱 Seed-Daten für Testing Features: - UUID Primary Keys - Soft Delete (deleted_at) - Auto-updated timestamps - GIN Index für Tags - Row-Level Security ready
This commit is contained in:
149
docs/ER-DIAGRAM.md
Normal file
149
docs/ER-DIAGRAM.md
Normal file
@@ -0,0 +1,149 @@
|
||||
# Pulse CRM - Entity Relationship Diagram
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
ORGANIZATIONS ||--o{ USERS : has
|
||||
ORGANIZATIONS ||--o{ CONTACTS : has
|
||||
ORGANIZATIONS ||--o{ COMPANIES : has
|
||||
ORGANIZATIONS ||--o{ PIPELINES : has
|
||||
ORGANIZATIONS ||--o{ DEALS : has
|
||||
ORGANIZATIONS ||--o{ ACTIVITIES : has
|
||||
ORGANIZATIONS ||--o{ AUDIT_LOGS : has
|
||||
|
||||
USERS ||--o{ CONTACTS : owns
|
||||
USERS ||--o{ COMPANIES : owns
|
||||
USERS ||--o{ DEALS : owns
|
||||
USERS ||--o{ ACTIVITIES : creates
|
||||
USERS ||--o{ REFRESH_TOKENS : has
|
||||
|
||||
COMPANIES ||--o{ CONTACTS : employs
|
||||
COMPANIES ||--o{ DEALS : has
|
||||
|
||||
CONTACTS ||--o{ DEALS : associated
|
||||
CONTACTS ||--o{ ACTIVITIES : has
|
||||
|
||||
PIPELINES ||--o{ DEALS : contains
|
||||
|
||||
DEALS ||--o{ ACTIVITIES : has
|
||||
|
||||
ORGANIZATIONS {
|
||||
uuid id PK
|
||||
string name
|
||||
string slug UK
|
||||
jsonb settings
|
||||
string subscription_plan
|
||||
timestamp created_at
|
||||
}
|
||||
|
||||
USERS {
|
||||
uuid id PK
|
||||
uuid org_id FK
|
||||
string email UK
|
||||
string password_hash
|
||||
string first_name
|
||||
string last_name
|
||||
string role
|
||||
boolean is_active
|
||||
timestamp last_login_at
|
||||
}
|
||||
|
||||
CONTACTS {
|
||||
uuid id PK
|
||||
uuid org_id FK
|
||||
uuid company_id FK
|
||||
uuid owner_id FK
|
||||
string first_name
|
||||
string last_name
|
||||
string email
|
||||
string phone
|
||||
string status
|
||||
boolean gdpr_consent
|
||||
timestamp deleted_at
|
||||
}
|
||||
|
||||
COMPANIES {
|
||||
uuid id PK
|
||||
uuid org_id FK
|
||||
uuid owner_id FK
|
||||
string name
|
||||
string industry
|
||||
string website
|
||||
string phone
|
||||
timestamp deleted_at
|
||||
}
|
||||
|
||||
PIPELINES {
|
||||
uuid id PK
|
||||
uuid org_id FK
|
||||
string name
|
||||
boolean is_default
|
||||
jsonb stages
|
||||
}
|
||||
|
||||
DEALS {
|
||||
uuid id PK
|
||||
uuid org_id FK
|
||||
uuid pipeline_id FK
|
||||
uuid contact_id FK
|
||||
uuid company_id FK
|
||||
uuid owner_id FK
|
||||
string title
|
||||
decimal value
|
||||
string stage_id
|
||||
string status
|
||||
date expected_close_date
|
||||
}
|
||||
|
||||
ACTIVITIES {
|
||||
uuid id PK
|
||||
uuid org_id FK
|
||||
uuid user_id FK
|
||||
uuid contact_id FK
|
||||
uuid deal_id FK
|
||||
string type
|
||||
string subject
|
||||
text description
|
||||
timestamp due_date
|
||||
boolean is_completed
|
||||
}
|
||||
|
||||
AUDIT_LOGS {
|
||||
uuid id PK
|
||||
uuid org_id FK
|
||||
uuid user_id FK
|
||||
string action
|
||||
string entity_type
|
||||
uuid entity_id
|
||||
jsonb changes
|
||||
inet ip_address
|
||||
}
|
||||
|
||||
REFRESH_TOKENS {
|
||||
uuid id PK
|
||||
uuid user_id FK
|
||||
string token_hash
|
||||
timestamp expires_at
|
||||
}
|
||||
```
|
||||
|
||||
## Tabellen-Übersicht
|
||||
|
||||
| Tabelle | Beschreibung | Relationships |
|
||||
|---------|--------------|---------------|
|
||||
| `organizations` | Mandanten (Multi-Tenancy) | Parent für alle Daten |
|
||||
| `users` | Benutzer/Team-Mitglieder | Gehört zu Organization |
|
||||
| `contacts` | Personen/Leads | Gehört zu Organization, optional zu Company |
|
||||
| `companies` | Firmen | Gehört zu Organization |
|
||||
| `pipelines` | Sales Pipelines | Gehört zu Organization |
|
||||
| `deals` | Opportunities | Gehört zu Pipeline, Contact, Company |
|
||||
| `activities` | Notizen, Calls, Tasks | Gehört zu Contact oder Deal |
|
||||
| `audit_logs` | DSGVO Audit Trail | Protokolliert alle Änderungen |
|
||||
| `refresh_tokens` | JWT Refresh Tokens | Gehört zu User |
|
||||
|
||||
## Indizes
|
||||
|
||||
Alle Tabellen haben Indizes auf:
|
||||
- `org_id` - Multi-Tenancy Queries
|
||||
- Foreign Keys
|
||||
- Häufig gefilterte Felder (status, email, etc.)
|
||||
- `deleted_at` - Soft Delete Queries
|
||||
320
src/db/schema.sql
Normal file
320
src/db/schema.sql
Normal file
@@ -0,0 +1,320 @@
|
||||
-- Pulse CRM Database Schema
|
||||
-- PostgreSQL 16+
|
||||
|
||||
-- Enable UUID extension
|
||||
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
|
||||
|
||||
-- ============================================
|
||||
-- ORGANIZATIONS (Multi-Tenancy)
|
||||
-- ============================================
|
||||
CREATE TABLE organizations (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
name VARCHAR(255) NOT NULL,
|
||||
slug VARCHAR(100) UNIQUE NOT NULL,
|
||||
settings JSONB DEFAULT '{}',
|
||||
subscription_plan VARCHAR(50) DEFAULT 'starter',
|
||||
subscription_status VARCHAR(50) DEFAULT 'active',
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_organizations_slug ON organizations(slug);
|
||||
|
||||
-- ============================================
|
||||
-- USERS
|
||||
-- ============================================
|
||||
CREATE TABLE 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,
|
||||
first_name VARCHAR(100),
|
||||
last_name VARCHAR(100),
|
||||
role VARCHAR(50) DEFAULT 'user', -- admin, manager, user
|
||||
avatar_url TEXT,
|
||||
phone VARCHAR(50),
|
||||
is_active BOOLEAN DEFAULT true,
|
||||
email_verified BOOLEAN DEFAULT false,
|
||||
last_login_at TIMESTAMP WITH TIME ZONE,
|
||||
settings JSONB DEFAULT '{}',
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
UNIQUE(org_id, email)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_users_org_id ON users(org_id);
|
||||
CREATE INDEX idx_users_email ON users(email);
|
||||
|
||||
-- ============================================
|
||||
-- CONTACTS
|
||||
-- ============================================
|
||||
CREATE TABLE contacts (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
org_id UUID NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
company_id UUID REFERENCES companies(id) ON DELETE SET NULL,
|
||||
owner_id UUID REFERENCES users(id) ON DELETE SET NULL,
|
||||
|
||||
-- Basic Info
|
||||
first_name VARCHAR(100),
|
||||
last_name VARCHAR(100),
|
||||
email VARCHAR(255),
|
||||
phone VARCHAR(50),
|
||||
mobile VARCHAR(50),
|
||||
job_title VARCHAR(100),
|
||||
|
||||
-- Address
|
||||
address_line1 VARCHAR(255),
|
||||
address_line2 VARCHAR(255),
|
||||
city VARCHAR(100),
|
||||
state VARCHAR(100),
|
||||
postal_code VARCHAR(20),
|
||||
country VARCHAR(100),
|
||||
|
||||
-- Social
|
||||
linkedin_url TEXT,
|
||||
twitter_handle VARCHAR(100),
|
||||
|
||||
-- Status
|
||||
status VARCHAR(50) DEFAULT 'active', -- active, inactive, archived
|
||||
lead_source VARCHAR(100),
|
||||
lead_score INTEGER DEFAULT 0,
|
||||
|
||||
-- Custom Fields
|
||||
custom_fields JSONB DEFAULT '{}',
|
||||
tags TEXT[] DEFAULT '{}',
|
||||
|
||||
-- DSGVO
|
||||
gdpr_consent BOOLEAN DEFAULT false,
|
||||
gdpr_consent_date TIMESTAMP WITH TIME ZONE,
|
||||
is_restricted BOOLEAN DEFAULT false, -- Art. 18 DSGVO
|
||||
|
||||
-- Timestamps
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
deleted_at TIMESTAMP WITH TIME ZONE -- Soft delete
|
||||
);
|
||||
|
||||
CREATE INDEX idx_contacts_org_id ON contacts(org_id);
|
||||
CREATE INDEX idx_contacts_company_id ON contacts(company_id);
|
||||
CREATE INDEX idx_contacts_owner_id ON contacts(owner_id);
|
||||
CREATE INDEX idx_contacts_email ON contacts(email);
|
||||
CREATE INDEX idx_contacts_tags ON contacts USING GIN(tags);
|
||||
CREATE INDEX idx_contacts_deleted_at ON contacts(deleted_at) WHERE deleted_at IS NULL;
|
||||
|
||||
-- ============================================
|
||||
-- COMPANIES
|
||||
-- ============================================
|
||||
CREATE TABLE companies (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
org_id UUID NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
owner_id UUID REFERENCES users(id) ON DELETE SET NULL,
|
||||
|
||||
-- Basic Info
|
||||
name VARCHAR(255) NOT NULL,
|
||||
industry VARCHAR(100),
|
||||
website VARCHAR(255),
|
||||
description TEXT,
|
||||
|
||||
-- Contact Info
|
||||
phone VARCHAR(50),
|
||||
email VARCHAR(255),
|
||||
|
||||
-- Address
|
||||
address_line1 VARCHAR(255),
|
||||
address_line2 VARCHAR(255),
|
||||
city VARCHAR(100),
|
||||
state VARCHAR(100),
|
||||
postal_code VARCHAR(20),
|
||||
country VARCHAR(100),
|
||||
|
||||
-- Business Info
|
||||
employee_count VARCHAR(50),
|
||||
annual_revenue VARCHAR(50),
|
||||
|
||||
-- Custom Fields
|
||||
custom_fields JSONB DEFAULT '{}',
|
||||
tags TEXT[] DEFAULT '{}',
|
||||
|
||||
-- Timestamps
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
deleted_at TIMESTAMP WITH TIME ZONE
|
||||
);
|
||||
|
||||
CREATE INDEX idx_companies_org_id ON companies(org_id);
|
||||
CREATE INDEX idx_companies_name ON companies(name);
|
||||
|
||||
-- ============================================
|
||||
-- PIPELINES
|
||||
-- ============================================
|
||||
CREATE TABLE pipelines (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
org_id UUID NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
name VARCHAR(255) NOT NULL,
|
||||
is_default BOOLEAN DEFAULT false,
|
||||
stages JSONB NOT NULL DEFAULT '[]',
|
||||
-- stages format: [{"id": "uuid", "name": "Lead", "order": 1, "probability": 10}, ...]
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_pipelines_org_id ON pipelines(org_id);
|
||||
|
||||
-- ============================================
|
||||
-- DEALS
|
||||
-- ============================================
|
||||
CREATE TABLE deals (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
org_id UUID NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
pipeline_id UUID NOT NULL REFERENCES pipelines(id) ON DELETE CASCADE,
|
||||
contact_id UUID REFERENCES contacts(id) ON DELETE SET NULL,
|
||||
company_id UUID REFERENCES companies(id) ON DELETE SET NULL,
|
||||
owner_id UUID REFERENCES users(id) ON DELETE SET NULL,
|
||||
|
||||
-- Deal Info
|
||||
title VARCHAR(255) NOT NULL,
|
||||
value DECIMAL(15, 2) DEFAULT 0,
|
||||
currency VARCHAR(3) DEFAULT 'EUR',
|
||||
stage_id VARCHAR(100) NOT NULL, -- References stages JSONB in pipelines
|
||||
probability INTEGER DEFAULT 0,
|
||||
|
||||
-- Dates
|
||||
expected_close_date DATE,
|
||||
actual_close_date DATE,
|
||||
|
||||
-- Status
|
||||
status VARCHAR(50) DEFAULT 'open', -- open, won, lost
|
||||
lost_reason VARCHAR(255),
|
||||
|
||||
-- Custom Fields
|
||||
custom_fields JSONB DEFAULT '{}',
|
||||
tags TEXT[] DEFAULT '{}',
|
||||
|
||||
-- Timestamps
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
deleted_at TIMESTAMP WITH TIME ZONE
|
||||
);
|
||||
|
||||
CREATE INDEX idx_deals_org_id ON deals(org_id);
|
||||
CREATE INDEX idx_deals_pipeline_id ON deals(pipeline_id);
|
||||
CREATE INDEX idx_deals_contact_id ON deals(contact_id);
|
||||
CREATE INDEX idx_deals_company_id ON deals(company_id);
|
||||
CREATE INDEX idx_deals_owner_id ON deals(owner_id);
|
||||
CREATE INDEX idx_deals_status ON deals(status);
|
||||
CREATE INDEX idx_deals_stage_id ON deals(stage_id);
|
||||
|
||||
-- ============================================
|
||||
-- ACTIVITIES
|
||||
-- ============================================
|
||||
CREATE TABLE activities (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
org_id UUID NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
contact_id UUID REFERENCES contacts(id) ON DELETE CASCADE,
|
||||
company_id UUID REFERENCES companies(id) ON DELETE CASCADE,
|
||||
deal_id UUID REFERENCES deals(id) ON DELETE CASCADE,
|
||||
|
||||
-- Activity Info
|
||||
type VARCHAR(50) NOT NULL, -- note, call, email, meeting, task
|
||||
subject VARCHAR(255),
|
||||
description TEXT,
|
||||
|
||||
-- For tasks/meetings
|
||||
due_date TIMESTAMP WITH TIME ZONE,
|
||||
completed_at TIMESTAMP WITH TIME ZONE,
|
||||
is_completed BOOLEAN DEFAULT false,
|
||||
|
||||
-- For calls
|
||||
duration_minutes INTEGER,
|
||||
call_outcome VARCHAR(50),
|
||||
|
||||
-- Timestamps
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_activities_org_id ON activities(org_id);
|
||||
CREATE INDEX idx_activities_user_id ON activities(user_id);
|
||||
CREATE INDEX idx_activities_contact_id ON activities(contact_id);
|
||||
CREATE INDEX idx_activities_deal_id ON activities(deal_id);
|
||||
CREATE INDEX idx_activities_type ON activities(type);
|
||||
CREATE INDEX idx_activities_due_date ON activities(due_date);
|
||||
|
||||
-- ============================================
|
||||
-- AUDIT LOG (DSGVO)
|
||||
-- ============================================
|
||||
CREATE TABLE audit_logs (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
org_id UUID NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
user_id UUID REFERENCES users(id) ON DELETE SET NULL,
|
||||
|
||||
-- Action Info
|
||||
action VARCHAR(50) NOT NULL, -- create, read, update, delete, export, login
|
||||
entity_type VARCHAR(50) NOT NULL, -- contact, deal, user, etc.
|
||||
entity_id UUID,
|
||||
|
||||
-- Changes
|
||||
changes JSONB, -- { before: {...}, after: {...} }
|
||||
|
||||
-- Context
|
||||
ip_address INET,
|
||||
user_agent TEXT,
|
||||
|
||||
-- Timestamp
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX idx_audit_logs_org_id ON audit_logs(org_id);
|
||||
CREATE INDEX idx_audit_logs_user_id ON audit_logs(user_id);
|
||||
CREATE INDEX idx_audit_logs_entity ON audit_logs(entity_type, entity_id);
|
||||
CREATE INDEX idx_audit_logs_created_at ON audit_logs(created_at);
|
||||
|
||||
-- ============================================
|
||||
-- REFRESH TOKENS
|
||||
-- ============================================
|
||||
CREATE TABLE 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(),
|
||||
revoked_at TIMESTAMP WITH TIME ZONE
|
||||
);
|
||||
|
||||
CREATE INDEX idx_refresh_tokens_user_id ON refresh_tokens(user_id);
|
||||
CREATE INDEX idx_refresh_tokens_token_hash ON refresh_tokens(token_hash);
|
||||
|
||||
-- ============================================
|
||||
-- TRIGGERS
|
||||
-- ============================================
|
||||
|
||||
-- Auto-update updated_at
|
||||
CREATE OR REPLACE FUNCTION update_updated_at_column()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.updated_at = NOW();
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ language 'plpgsql';
|
||||
|
||||
CREATE TRIGGER update_organizations_updated_at BEFORE UPDATE ON organizations
|
||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
CREATE TRIGGER update_users_updated_at BEFORE UPDATE ON users
|
||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
CREATE TRIGGER update_contacts_updated_at BEFORE UPDATE ON contacts
|
||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
CREATE TRIGGER update_companies_updated_at BEFORE UPDATE ON companies
|
||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
CREATE TRIGGER update_pipelines_updated_at BEFORE UPDATE ON pipelines
|
||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
CREATE TRIGGER update_deals_updated_at BEFORE UPDATE ON deals
|
||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
|
||||
CREATE TRIGGER update_activities_updated_at BEFORE UPDATE ON activities
|
||||
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
|
||||
70
src/db/seed.sql
Normal file
70
src/db/seed.sql
Normal file
@@ -0,0 +1,70 @@
|
||||
-- Pulse CRM Seed Data
|
||||
-- For development/testing only
|
||||
|
||||
-- ============================================
|
||||
-- ORGANIZATION
|
||||
-- ============================================
|
||||
INSERT INTO organizations (id, name, slug, subscription_plan) VALUES
|
||||
('11111111-1111-1111-1111-111111111111', 'Demo Company GmbH', 'demo-company', 'pro');
|
||||
|
||||
-- ============================================
|
||||
-- USERS
|
||||
-- Password: 'demo1234' (Argon2 hash)
|
||||
-- ============================================
|
||||
INSERT INTO users (id, org_id, email, password_hash, first_name, last_name, role, email_verified) VALUES
|
||||
('22222222-2222-2222-2222-222222222222', '11111111-1111-1111-1111-111111111111', 'admin@demo.de', '$argon2id$v=19$m=65536,t=3,p=4$randomsalt$hashedpassword', 'Max', 'Mustermann', 'admin', true),
|
||||
('22222222-2222-2222-2222-222222222223', '11111111-1111-1111-1111-111111111111', 'sales@demo.de', '$argon2id$v=19$m=65536,t=3,p=4$randomsalt$hashedpassword', 'Lisa', 'Schmidt', 'user', true);
|
||||
|
||||
-- ============================================
|
||||
-- PIPELINE
|
||||
-- ============================================
|
||||
INSERT INTO pipelines (id, org_id, name, is_default, stages) VALUES
|
||||
('33333333-3333-3333-3333-333333333333', '11111111-1111-1111-1111-111111111111', 'Sales Pipeline', true,
|
||||
'[
|
||||
{"id": "lead", "name": "Lead", "order": 1, "probability": 10},
|
||||
{"id": "qualified", "name": "Qualifiziert", "order": 2, "probability": 25},
|
||||
{"id": "proposal", "name": "Angebot", "order": 3, "probability": 50},
|
||||
{"id": "negotiation", "name": "Verhandlung", "order": 4, "probability": 75},
|
||||
{"id": "closed_won", "name": "Gewonnen", "order": 5, "probability": 100},
|
||||
{"id": "closed_lost", "name": "Verloren", "order": 6, "probability": 0}
|
||||
]');
|
||||
|
||||
-- ============================================
|
||||
-- COMPANIES
|
||||
-- ============================================
|
||||
INSERT INTO companies (id, org_id, owner_id, name, industry, website, phone, city, country) VALUES
|
||||
('44444444-4444-4444-4444-444444444444', '11111111-1111-1111-1111-111111111111', '22222222-2222-2222-2222-222222222222', 'TechStart GmbH', 'Technologie', 'https://techstart.de', '+49 30 123456', 'Berlin', 'Deutschland'),
|
||||
('44444444-4444-4444-4444-444444444445', '11111111-1111-1111-1111-111111111111', '22222222-2222-2222-2222-222222222223', 'DataFlow AG', 'Software', 'https://dataflow.de', '+49 89 654321', 'München', 'Deutschland'),
|
||||
('44444444-4444-4444-4444-444444444446', '11111111-1111-1111-1111-111111111111', '22222222-2222-2222-2222-222222222222', 'ScaleUp Solutions', 'Beratung', 'https://scaleup.de', '+49 40 789012', 'Hamburg', 'Deutschland');
|
||||
|
||||
-- ============================================
|
||||
-- CONTACTS
|
||||
-- ============================================
|
||||
INSERT INTO contacts (id, org_id, company_id, owner_id, first_name, last_name, email, phone, job_title, status, gdpr_consent, gdpr_consent_date, tags) VALUES
|
||||
('55555555-5555-5555-5555-555555555555', '11111111-1111-1111-1111-111111111111', '44444444-4444-4444-4444-444444444444', '22222222-2222-2222-2222-222222222222', 'Sarah', 'Müller', 'sarah.mueller@techstart.de', '+49 30 111222', 'CEO', 'active', true, NOW(), ARRAY['Entscheider', 'VIP']),
|
||||
('55555555-5555-5555-5555-555555555556', '11111111-1111-1111-1111-111111111111', '44444444-4444-4444-4444-444444444444', '22222222-2222-2222-2222-222222222222', 'Thomas', 'Weber', 'thomas.weber@techstart.de', '+49 30 111223', 'CTO', 'active', true, NOW(), ARRAY['Technik']),
|
||||
('55555555-5555-5555-5555-555555555557', '11111111-1111-1111-1111-111111111111', '44444444-4444-4444-4444-444444444445', '22222222-2222-2222-2222-222222222223', 'Anna', 'Becker', 'anna.becker@dataflow.de', '+49 89 222333', 'Head of Sales', 'active', true, NOW(), ARRAY['Sales', 'Entscheider']),
|
||||
('55555555-5555-5555-5555-555555555558', '11111111-1111-1111-1111-111111111111', '44444444-4444-4444-4444-444444444446', '22222222-2222-2222-2222-222222222223', 'Michael', 'Fischer', 'michael.fischer@scaleup.de', '+49 40 333444', 'Managing Partner', 'active', true, NOW(), ARRAY['Partner', 'Entscheider']);
|
||||
|
||||
-- ============================================
|
||||
-- DEALS
|
||||
-- ============================================
|
||||
INSERT INTO deals (id, org_id, pipeline_id, contact_id, company_id, owner_id, title, value, stage_id, status, expected_close_date, tags) VALUES
|
||||
('66666666-6666-6666-6666-666666666666', '11111111-1111-1111-1111-111111111111', '33333333-3333-3333-3333-333333333333', '55555555-5555-5555-5555-555555555555', '44444444-4444-4444-4444-444444444444', '22222222-2222-2222-2222-222222222222', 'TechStart CRM Implementation', 25000.00, 'proposal', 'open', '2026-03-15', ARRAY['Enterprise']),
|
||||
('66666666-6666-6666-6666-666666666667', '11111111-1111-1111-1111-111111111111', '33333333-3333-3333-3333-333333333333', '55555555-5555-5555-5555-555555555557', '44444444-4444-4444-4444-444444444445', '22222222-2222-2222-2222-222222222223', 'DataFlow Integration Projekt', 15000.00, 'qualified', 'open', '2026-04-01', ARRAY['Integration']),
|
||||
('66666666-6666-6666-6666-666666666668', '11111111-1111-1111-1111-111111111111', '33333333-3333-3333-3333-333333333333', '55555555-5555-5555-5555-555555555558', '44444444-4444-4444-4444-444444444446', '22222222-2222-2222-2222-222222222222', 'ScaleUp Consulting Deal', 50000.00, 'negotiation', 'open', '2026-02-28', ARRAY['Beratung', 'High Value']);
|
||||
|
||||
-- ============================================
|
||||
-- ACTIVITIES
|
||||
-- ============================================
|
||||
INSERT INTO activities (id, org_id, user_id, contact_id, deal_id, type, subject, description, due_date, is_completed) VALUES
|
||||
('77777777-7777-7777-7777-777777777777', '11111111-1111-1111-1111-111111111111', '22222222-2222-2222-2222-222222222222', '55555555-5555-5555-5555-555555555555', '66666666-6666-6666-6666-666666666666', 'call', 'Erstgespräch', 'Sehr interessiert an CRM Lösung. Termin für Demo vereinbart.', NULL, true),
|
||||
('77777777-7777-7777-7777-777777777778', '11111111-1111-1111-1111-111111111111', '22222222-2222-2222-2222-222222222222', '55555555-5555-5555-5555-555555555555', '66666666-6666-6666-6666-666666666666', 'meeting', 'Demo Präsentation', 'Demo für das ganze Team zeigen', '2026-02-15 14:00:00', false),
|
||||
('77777777-7777-7777-7777-777777777779', '11111111-1111-1111-1111-111111111111', '22222222-2222-2222-2222-222222222223', '55555555-5555-5555-5555-555555555557', '66666666-6666-6666-6666-666666666667', 'note', 'Anforderungen', 'Benötigt: API Integration mit bestehendem ERP System', NULL, true),
|
||||
('77777777-7777-7777-7777-777777777780', '11111111-1111-1111-1111-111111111111', '22222222-2222-2222-2222-222222222222', '55555555-5555-5555-5555-555555555558', '66666666-6666-6666-6666-666666666668', 'task', 'Angebot erstellen', 'Individuelles Angebot mit Mengenrabatt', '2026-02-12 17:00:00', false);
|
||||
|
||||
-- ============================================
|
||||
-- AUDIT LOG EXAMPLE
|
||||
-- ============================================
|
||||
INSERT INTO audit_logs (org_id, user_id, action, entity_type, entity_id, changes, ip_address) VALUES
|
||||
('11111111-1111-1111-1111-111111111111', '22222222-2222-2222-2222-222222222222', 'create', 'contact', '55555555-5555-5555-5555-555555555555', '{"after": {"first_name": "Sarah", "last_name": "Müller"}}', '192.168.1.1');
|
||||
Reference in New Issue
Block a user