Added support for Streamdeck Pedal and updated UI to better fit the Packed UI style
This commit is contained in:
270
pirp/schema.sql
Normal file
270
pirp/schema.sql
Normal file
@@ -0,0 +1,270 @@
|
||||
-- PIRP vollständiges Schema (inkl. Journal-Modul)
|
||||
|
||||
-- Reihenfolge beachten wegen Foreign Keys
|
||||
DROP TABLE IF EXISTS journal_monthly_summary_values CASCADE;
|
||||
DROP TABLE IF EXISTS journal_monthly_summary CASCADE;
|
||||
DROP TABLE IF EXISTS journal_entry_accounts CASCADE;
|
||||
DROP TABLE IF EXISTS journal_entries CASCADE;
|
||||
DROP TABLE IF EXISTS journal_summary_items CASCADE;
|
||||
DROP TABLE IF EXISTS journal_deduction_categories CASCADE;
|
||||
DROP TABLE IF EXISTS journal_expense_categories CASCADE;
|
||||
DROP TABLE IF EXISTS journal_revenue_categories CASCADE;
|
||||
DROP TABLE IF EXISTS journal_suppliers CASCADE;
|
||||
DROP TABLE IF EXISTS journal_years CASCADE;
|
||||
DROP TABLE IF EXISTS recurring_log CASCADE;
|
||||
DROP TABLE IF EXISTS recurring_template_items CASCADE;
|
||||
DROP TABLE IF EXISTS recurring_templates CASCADE;
|
||||
DROP TABLE IF EXISTS invoice_items CASCADE;
|
||||
DROP TABLE IF EXISTS invoices CASCADE;
|
||||
DROP TABLE IF EXISTS expenses CASCADE;
|
||||
DROP TABLE IF EXISTS customers CASCADE;
|
||||
DROP TABLE IF EXISTS settings CASCADE;
|
||||
DROP TABLE IF EXISTS users CASCADE;
|
||||
|
||||
-- ============================================================
|
||||
-- Basis-Tabellen
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE users (
|
||||
id SERIAL PRIMARY KEY,
|
||||
username VARCHAR(50) UNIQUE NOT NULL,
|
||||
password_hash TEXT NOT NULL,
|
||||
created_at TIMESTAMPTZ DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE settings (
|
||||
id SERIAL PRIMARY KEY,
|
||||
company_name TEXT,
|
||||
company_address TEXT,
|
||||
company_zip TEXT,
|
||||
company_city TEXT,
|
||||
company_country TEXT,
|
||||
tax_id TEXT,
|
||||
vat_mode VARCHAR(10) DEFAULT 'klein',
|
||||
default_vat_rate NUMERIC(5,2) DEFAULT 19.00,
|
||||
payment_terms TEXT,
|
||||
footer_text TEXT,
|
||||
logo_path TEXT,
|
||||
iban TEXT,
|
||||
phone TEXT,
|
||||
email TEXT,
|
||||
website TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE customers (
|
||||
id SERIAL PRIMARY KEY,
|
||||
customer_number VARCHAR(20) UNIQUE,
|
||||
name TEXT NOT NULL,
|
||||
address TEXT,
|
||||
zip TEXT,
|
||||
city TEXT,
|
||||
country TEXT,
|
||||
created_at TIMESTAMPTZ DEFAULT now()
|
||||
);
|
||||
|
||||
-- ============================================================
|
||||
-- Rechnungen
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE invoices (
|
||||
id SERIAL PRIMARY KEY,
|
||||
invoice_number VARCHAR(50) UNIQUE NOT NULL,
|
||||
customer_id INTEGER NOT NULL REFERENCES customers(id) ON DELETE RESTRICT,
|
||||
invoice_date DATE NOT NULL,
|
||||
service_date DATE,
|
||||
vat_mode VARCHAR(10) NOT NULL DEFAULT 'klein',
|
||||
vat_rate NUMERIC(5,2) NOT NULL DEFAULT 19.00,
|
||||
payment_terms TEXT,
|
||||
notes_internal TEXT,
|
||||
total_net NUMERIC(12,2) NOT NULL DEFAULT 0,
|
||||
total_vat NUMERIC(12,2) NOT NULL DEFAULT 0,
|
||||
total_gross NUMERIC(12,2) NOT NULL DEFAULT 0,
|
||||
paid BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
payment_date DATE,
|
||||
pdf_path TEXT,
|
||||
pdf_hash VARCHAR(64),
|
||||
pdf_generated_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE invoice_items (
|
||||
id SERIAL PRIMARY KEY,
|
||||
invoice_id INTEGER NOT NULL REFERENCES invoices(id) ON DELETE CASCADE,
|
||||
position_no INTEGER NOT NULL,
|
||||
description TEXT NOT NULL,
|
||||
quantity NUMERIC(12,2) NOT NULL DEFAULT 1,
|
||||
unit_price NUMERIC(12,2) NOT NULL DEFAULT 0,
|
||||
vat_rate NUMERIC(5,2) NOT NULL DEFAULT 19.00
|
||||
);
|
||||
|
||||
-- ============================================================
|
||||
-- Ausgaben
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE expenses (
|
||||
id SERIAL PRIMARY KEY,
|
||||
expense_date DATE NOT NULL,
|
||||
description TEXT NOT NULL,
|
||||
category TEXT,
|
||||
amount NUMERIC(12,2) NOT NULL,
|
||||
vat_rate NUMERIC(5,2) DEFAULT 0,
|
||||
total_net NUMERIC(12,2),
|
||||
total_vat NUMERIC(12,2) DEFAULT 0,
|
||||
expense_category_id INTEGER,
|
||||
paid BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
payment_date DATE,
|
||||
attachment_path TEXT,
|
||||
created_at TIMESTAMPTZ DEFAULT now()
|
||||
);
|
||||
|
||||
-- ============================================================
|
||||
-- Wiederkehrende Rechnungen (Abo-Rechnungen)
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE recurring_templates (
|
||||
id SERIAL PRIMARY KEY,
|
||||
template_name VARCHAR(100) NOT NULL,
|
||||
customer_id INTEGER NOT NULL REFERENCES customers(id) ON DELETE RESTRICT,
|
||||
interval_type VARCHAR(20) NOT NULL CHECK (interval_type IN ('monthly', 'quarterly', 'yearly')),
|
||||
start_date DATE NOT NULL,
|
||||
end_date DATE,
|
||||
next_due_date DATE NOT NULL,
|
||||
vat_mode VARCHAR(10) NOT NULL DEFAULT 'klein',
|
||||
vat_rate NUMERIC(5,2) NOT NULL DEFAULT 19.00,
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE,
|
||||
notes_internal TEXT,
|
||||
created_at TIMESTAMPTZ DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE recurring_template_items (
|
||||
id SERIAL PRIMARY KEY,
|
||||
template_id INTEGER NOT NULL REFERENCES recurring_templates(id) ON DELETE CASCADE,
|
||||
position_no INTEGER NOT NULL,
|
||||
description TEXT NOT NULL,
|
||||
quantity NUMERIC(12,2) NOT NULL DEFAULT 1,
|
||||
unit_price NUMERIC(12,2) NOT NULL DEFAULT 0
|
||||
);
|
||||
|
||||
CREATE TABLE recurring_log (
|
||||
id SERIAL PRIMARY KEY,
|
||||
template_id INTEGER NOT NULL REFERENCES recurring_templates(id) ON DELETE CASCADE,
|
||||
invoice_id INTEGER REFERENCES invoices(id) ON DELETE SET NULL,
|
||||
generated_at TIMESTAMPTZ DEFAULT now(),
|
||||
due_date DATE NOT NULL,
|
||||
status VARCHAR(20) NOT NULL DEFAULT 'generated'
|
||||
);
|
||||
|
||||
-- ============================================================
|
||||
-- Journal-Modul: Doppelte Buchführung
|
||||
-- ============================================================
|
||||
|
||||
CREATE TABLE journal_years (
|
||||
id SERIAL PRIMARY KEY,
|
||||
year INTEGER NOT NULL UNIQUE,
|
||||
is_closed BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
notes TEXT,
|
||||
created_at TIMESTAMPTZ DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE journal_suppliers (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE
|
||||
);
|
||||
|
||||
CREATE TABLE journal_revenue_categories (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
category_type VARCHAR(20) NOT NULL CHECK (category_type IN ('wareneingang', 'erloese')),
|
||||
vat_rate NUMERIC(5,2) NOT NULL DEFAULT 19.00,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE
|
||||
);
|
||||
|
||||
CREATE TABLE journal_expense_categories (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
side VARCHAR(10) NOT NULL DEFAULT 'soll' CHECK (side IN ('soll', 'soll_haben')),
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE
|
||||
);
|
||||
|
||||
CREATE TABLE journal_deduction_categories (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE
|
||||
);
|
||||
|
||||
CREATE TABLE journal_entries (
|
||||
id SERIAL PRIMARY KEY,
|
||||
year_id INTEGER NOT NULL REFERENCES journal_years(id) ON DELETE RESTRICT,
|
||||
entry_date DATE NOT NULL,
|
||||
month INTEGER NOT NULL CHECK (month BETWEEN 1 AND 12),
|
||||
description TEXT NOT NULL,
|
||||
attachment_note TEXT,
|
||||
amount NUMERIC(12,2) NOT NULL DEFAULT 0,
|
||||
supplier_id INTEGER REFERENCES journal_suppliers(id) ON DELETE SET NULL,
|
||||
invoice_id INTEGER REFERENCES invoices(id) ON DELETE SET NULL,
|
||||
expense_id INTEGER REFERENCES expenses(id) ON DELETE SET NULL,
|
||||
source_type VARCHAR(20) DEFAULT 'manual',
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
created_at TIMESTAMPTZ DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE journal_entry_accounts (
|
||||
id SERIAL PRIMARY KEY,
|
||||
entry_id INTEGER NOT NULL REFERENCES journal_entries(id) ON DELETE CASCADE,
|
||||
account_type VARCHAR(20) NOT NULL,
|
||||
side VARCHAR(5) NOT NULL CHECK (side IN ('soll', 'haben')),
|
||||
amount NUMERIC(12,2) NOT NULL DEFAULT 0,
|
||||
revenue_category_id INTEGER REFERENCES journal_revenue_categories(id) ON DELETE SET NULL,
|
||||
expense_category_id INTEGER REFERENCES journal_expense_categories(id) ON DELETE SET NULL,
|
||||
note TEXT
|
||||
);
|
||||
|
||||
CREATE TABLE journal_monthly_summary (
|
||||
id SERIAL PRIMARY KEY,
|
||||
year_id INTEGER NOT NULL REFERENCES journal_years(id) ON DELETE CASCADE,
|
||||
month INTEGER NOT NULL CHECK (month BETWEEN 1 AND 12),
|
||||
manual_corrections JSONB DEFAULT '{}',
|
||||
notes TEXT,
|
||||
UNIQUE(year_id, month)
|
||||
);
|
||||
|
||||
CREATE TABLE journal_summary_items (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_active BOOLEAN NOT NULL DEFAULT TRUE
|
||||
);
|
||||
|
||||
CREATE TABLE journal_monthly_summary_values (
|
||||
id SERIAL PRIMARY KEY,
|
||||
year_id INTEGER NOT NULL REFERENCES journal_years(id) ON DELETE CASCADE,
|
||||
month INTEGER NOT NULL CHECK (month BETWEEN 1 AND 12),
|
||||
summary_item_id INTEGER NOT NULL REFERENCES journal_summary_items(id) ON DELETE CASCADE,
|
||||
amount NUMERIC(12,2) NOT NULL DEFAULT 0,
|
||||
UNIQUE(year_id, month, summary_item_id)
|
||||
);
|
||||
|
||||
-- Foreign Key für expenses -> journal_expense_categories (nachträglich, da Tabelle erst jetzt existiert)
|
||||
ALTER TABLE expenses ADD CONSTRAINT fk_expenses_category
|
||||
FOREIGN KEY (expense_category_id) REFERENCES journal_expense_categories(id) ON DELETE SET NULL;
|
||||
|
||||
-- ============================================================
|
||||
-- Indizes
|
||||
-- ============================================================
|
||||
|
||||
CREATE INDEX idx_journal_entries_year_month ON journal_entries(year_id, month);
|
||||
CREATE INDEX idx_journal_entries_date ON journal_entries(entry_date);
|
||||
CREATE INDEX idx_journal_entries_invoice ON journal_entries(invoice_id);
|
||||
CREATE INDEX idx_journal_entries_expense ON journal_entries(expense_id);
|
||||
CREATE INDEX idx_journal_entries_source ON journal_entries(source_type);
|
||||
|
||||
-- Unique-Constraints: max. 1 Journal-Eintrag pro Rechnung/Ausgabe (verhindert Doppelbuchungen)
|
||||
CREATE UNIQUE INDEX idx_unique_journal_invoice ON journal_entries(invoice_id) WHERE invoice_id IS NOT NULL;
|
||||
CREATE UNIQUE INDEX idx_unique_journal_expense ON journal_entries(expense_id) WHERE expense_id IS NOT NULL;
|
||||
CREATE INDEX idx_journal_entry_accounts_entry ON journal_entry_accounts(entry_id);
|
||||
CREATE INDEX idx_journal_entry_accounts_type ON journal_entry_accounts(account_type);
|
||||
Reference in New Issue
Block a user