🤝 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