🤝 Subunternehmer-Modul: DB-Migration
This commit is contained in:
198
db/migrations/002_partnerships.sql
Normal file
198
db/migrations/002_partnerships.sql
Normal file
@@ -0,0 +1,198 @@
|
||||
-- SeCu Partnerships (Subunternehmer-System)
|
||||
-- Version: 1.1.0
|
||||
|
||||
-- Partnerschaften zwischen Organisationen
|
||||
CREATE TABLE IF NOT EXISTS org_partnerships (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
|
||||
-- Hauptunternehmer (der Aufträge vergibt)
|
||||
contractor_org_id UUID NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
|
||||
-- Subunternehmer (der Mitarbeiter stellt)
|
||||
subcontractor_org_id UUID NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
||||
|
||||
-- Status der Partnerschaft
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'pending'
|
||||
CHECK (status IN ('pending', 'active', 'paused', 'terminated')),
|
||||
|
||||
-- Vertragsdetails
|
||||
contract_start DATE,
|
||||
contract_end DATE,
|
||||
notes TEXT,
|
||||
|
||||
-- Wer hat eingeladen
|
||||
invited_by UUID REFERENCES users(id),
|
||||
accepted_by UUID REFERENCES users(id),
|
||||
accepted_at TIMESTAMP WITH TIME ZONE,
|
||||
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
|
||||
-- Ein Subunternehmer kann nur einmal pro Hauptunternehmer existieren
|
||||
UNIQUE(contractor_org_id, subcontractor_org_id),
|
||||
|
||||
-- Keine Selbst-Partnerschaft
|
||||
CHECK (contractor_org_id != subcontractor_org_id)
|
||||
);
|
||||
|
||||
-- Stundensätze und Konditionen pro Partnerschaft
|
||||
CREATE TABLE IF NOT EXISTS partnership_rates (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
partnership_id UUID NOT NULL REFERENCES org_partnerships(id) ON DELETE CASCADE,
|
||||
|
||||
-- Art des Satzes
|
||||
rate_type VARCHAR(50) NOT NULL DEFAULT 'hourly', -- hourly, daily, fixed, per_order
|
||||
|
||||
-- Bezeichnung (z.B. "Normaldienst", "Nachtdienst", "Wochenende")
|
||||
name VARCHAR(100) NOT NULL,
|
||||
description TEXT,
|
||||
|
||||
-- Betrag in Cent (für Genauigkeit)
|
||||
amount_cents INTEGER NOT NULL,
|
||||
currency VARCHAR(3) DEFAULT 'EUR',
|
||||
|
||||
-- Gültigkeit
|
||||
valid_from DATE DEFAULT CURRENT_DATE,
|
||||
valid_until DATE,
|
||||
|
||||
-- Standard-Satz?
|
||||
is_default BOOLEAN DEFAULT false,
|
||||
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Geteilte Aufträge (Hauptunternehmer -> Subunternehmer)
|
||||
CREATE TABLE IF NOT EXISTS shared_orders (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
partnership_id UUID NOT NULL REFERENCES org_partnerships(id) ON DELETE CASCADE,
|
||||
|
||||
-- Original-Auftrag beim Hauptunternehmer
|
||||
original_order_id UUID NOT NULL REFERENCES orders(id) ON DELETE CASCADE,
|
||||
|
||||
-- Kopie/Referenz beim Subunternehmer (optional, wenn sie eigene Aufträge anlegen)
|
||||
sub_order_id UUID REFERENCES orders(id) ON DELETE SET NULL,
|
||||
|
||||
-- Welcher Satz gilt für diesen Auftrag
|
||||
rate_id UUID REFERENCES partnership_rates(id),
|
||||
|
||||
-- Anzahl benötigter Mitarbeiter vom Subunternehmer
|
||||
required_staff INTEGER DEFAULT 1,
|
||||
|
||||
-- Status
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'requested'
|
||||
CHECK (status IN ('requested', 'accepted', 'declined', 'completed', 'cancelled')),
|
||||
|
||||
-- Notizen zwischen den Unternehmen
|
||||
contractor_notes TEXT,
|
||||
subcontractor_notes TEXT,
|
||||
|
||||
responded_at TIMESTAMP WITH TIME ZONE,
|
||||
completed_at TIMESTAMP WITH TIME ZONE,
|
||||
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Stundenzettel von Subunternehmer-Mitarbeitern für geteilte Aufträge
|
||||
CREATE TABLE IF NOT EXISTS partnership_timesheets (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
shared_order_id UUID NOT NULL REFERENCES shared_orders(id) ON DELETE CASCADE,
|
||||
|
||||
-- Original-Stundenzettel beim Subunternehmer
|
||||
timesheet_id UUID NOT NULL REFERENCES timesheets(id) ON DELETE CASCADE,
|
||||
|
||||
-- Welcher Satz wurde angewendet
|
||||
rate_id UUID REFERENCES partnership_rates(id),
|
||||
|
||||
-- Berechneter Betrag
|
||||
calculated_amount_cents INTEGER,
|
||||
|
||||
-- Status der Freigabe durch Hauptunternehmer
|
||||
approval_status VARCHAR(20) DEFAULT 'pending'
|
||||
CHECK (approval_status IN ('pending', 'approved', 'disputed', 'rejected')),
|
||||
|
||||
approved_by UUID REFERENCES users(id),
|
||||
approved_at TIMESTAMP WITH TIME ZONE,
|
||||
dispute_reason TEXT,
|
||||
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Abrechnungen zwischen Partnern
|
||||
CREATE TABLE IF NOT EXISTS partnership_invoices (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
partnership_id UUID NOT NULL REFERENCES org_partnerships(id) ON DELETE CASCADE,
|
||||
|
||||
-- Rechnungsnummer
|
||||
invoice_number VARCHAR(50) NOT NULL,
|
||||
|
||||
-- Abrechnungszeitraum
|
||||
period_start DATE NOT NULL,
|
||||
period_end DATE NOT NULL,
|
||||
|
||||
-- Beträge
|
||||
subtotal_cents INTEGER NOT NULL DEFAULT 0,
|
||||
tax_percent DECIMAL(5,2) DEFAULT 19.00,
|
||||
tax_cents INTEGER NOT NULL DEFAULT 0,
|
||||
total_cents INTEGER NOT NULL DEFAULT 0,
|
||||
|
||||
-- Status
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'draft'
|
||||
CHECK (status IN ('draft', 'sent', 'paid', 'overdue', 'cancelled')),
|
||||
|
||||
-- Daten
|
||||
issued_at TIMESTAMP WITH TIME ZONE,
|
||||
due_date DATE,
|
||||
paid_at TIMESTAMP WITH TIME ZONE,
|
||||
|
||||
-- PDF-Link (wenn generiert)
|
||||
pdf_url TEXT,
|
||||
|
||||
-- Notizen
|
||||
notes TEXT,
|
||||
|
||||
created_by UUID REFERENCES users(id),
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||||
updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Rechnungspositionen
|
||||
CREATE TABLE IF NOT EXISTS partnership_invoice_items (
|
||||
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
|
||||
invoice_id UUID NOT NULL REFERENCES partnership_invoices(id) ON DELETE CASCADE,
|
||||
|
||||
-- Referenz zum Stundenzettel (optional)
|
||||
partnership_timesheet_id UUID REFERENCES partnership_timesheets(id),
|
||||
|
||||
-- Beschreibung
|
||||
description TEXT NOT NULL,
|
||||
|
||||
-- Mengen und Preise
|
||||
quantity DECIMAL(10,2) NOT NULL DEFAULT 1,
|
||||
unit VARCHAR(20) DEFAULT 'Stunden',
|
||||
unit_price_cents INTEGER NOT NULL,
|
||||
total_cents INTEGER NOT NULL,
|
||||
|
||||
-- Datum der Leistung
|
||||
service_date DATE,
|
||||
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||||
);
|
||||
|
||||
-- Indexes
|
||||
CREATE INDEX IF NOT EXISTS idx_partnerships_contractor ON org_partnerships(contractor_org_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_partnerships_subcontractor ON org_partnerships(subcontractor_org_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_partnerships_status ON org_partnerships(status);
|
||||
CREATE INDEX IF NOT EXISTS idx_shared_orders_partnership ON shared_orders(partnership_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_shared_orders_original ON shared_orders(original_order_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_partnership_timesheets_shared ON partnership_timesheets(shared_order_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_partnership_invoices_partnership ON partnership_invoices(partnership_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_partnership_invoices_status ON partnership_invoices(status);
|
||||
|
||||
-- Partnership-Modul registrieren
|
||||
INSERT INTO modules (name, display_name, description, is_core, default_config) VALUES
|
||||
('partnerships', 'Subunternehmer', 'Zusammenarbeit mit Subunternehmen inkl. Abrechnung', false,
|
||||
'{"auto_approve_timesheets": false, "default_payment_days": 30}')
|
||||
ON CONFLICT (name) DO NOTHING;
|
||||
Reference in New Issue
Block a user