-- Create invoice management tables -- Migration: 20250110000002_create_invoice_tables -- Invoice settings table CREATE TABLE invoice_settings ( id SERIAL PRIMARY KEY, company_name VARCHAR(255) NOT NULL, company_ico VARCHAR(20) NOT NULL, company_dic VARCHAR(20), company_address TEXT, company_city VARCHAR(100), company_zip VARCHAR(10), company_country VARCHAR(100) DEFAULT 'Česká republika', bank_name VARCHAR(255), bank_account VARCHAR(50), bank_iban VARCHAR(50), bank_swift VARCHAR(20), invoice_number_format VARCHAR(100) DEFAULT 'F{year}{seq:6}', next_invoice_number INTEGER DEFAULT 1, current_year INTEGER, default_payment_term INTEGER DEFAULT 14, default_vat_rate DECIMAL(5,2) DEFAULT 21.0, default_currency VARCHAR(3) DEFAULT 'CZK', email_from VARCHAR(255), email_subject VARCHAR(255) DEFAULT 'Faktura č. {invoice_number}', email_body TEXT, pdf_logo_path VARCHAR(500), pdf_footer TEXT, registration_number VARCHAR(50), tax_registration_number VARCHAR(50), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_by INTEGER ); -- Invoice customers table CREATE TABLE invoice_customers ( id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, ico VARCHAR(20) UNIQUE, dic VARCHAR(20), address TEXT, city VARCHAR(100), zip VARCHAR(10), country VARCHAR(100) DEFAULT 'Česká republika', email VARCHAR(255), phone VARCHAR(50), website VARCHAR(255), business_type VARCHAR(100), vat_payer BOOLEAN DEFAULT true, notes TEXT, active BOOLEAN DEFAULT true, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_by INTEGER, updated_by INTEGER ); CREATE INDEX idx_invoice_customers_ico ON invoice_customers(ico); CREATE INDEX idx_invoice_customers_active ON invoice_customers(active); CREATE INDEX idx_invoice_customers_name ON invoice_customers(name); -- Invoice sequences table CREATE TABLE invoice_sequences ( id SERIAL PRIMARY KEY, type VARCHAR(50) NOT NULL, year INTEGER NOT NULL, current_number INTEGER DEFAULT 1, prefix VARCHAR(20), suffix VARCHAR(20), padding INTEGER DEFAULT 6, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, UNIQUE(type, year) ); -- Insert default sequences INSERT INTO invoice_sequences (type, year, current_number, prefix) VALUES ('faktura', EXTRACT(YEAR FROM CURRENT_DATE), 1, 'F'), ('zalohova_faktura', EXTRACT(YEAR FROM CURRENT_DATE), 1, 'ZF'), ('proforma_faktura', EXTRACT(YEAR FROM CURRENT_DATE), 1, 'PF'), ('dobropis', EXTRACT(YEAR FROM CURRENT_DATE), 1, 'D'); -- Invoice templates table CREATE TABLE invoice_templates ( id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL, type VARCHAR(50) NOT NULL, description TEXT, header_html TEXT, body_html TEXT, footer_html TEXT, css TEXT, default_vat_rate DECIMAL(5,2) DEFAULT 21.0, default_payment_term INTEGER DEFAULT 14, active BOOLEAN DEFAULT true, default BOOLEAN DEFAULT false, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_by INTEGER, updated_by INTEGER ); -- Invoices table CREATE TABLE invoices ( id SERIAL PRIMARY KEY, invoice_number VARCHAR(50) NOT NULL UNIQUE, invoice_type VARCHAR(20) DEFAULT 'faktura', variable_symbol VARCHAR(20), constant_symbol VARCHAR(20), specific_symbol VARCHAR(20), issue_date TIMESTAMP NOT NULL, due_date TIMESTAMP NOT NULL, taxable_supply_date TIMESTAMP, -- Supplier information (auto-filled) supplier_name VARCHAR(255) NOT NULL, supplier_ico VARCHAR(20), supplier_dic VARCHAR(20), supplier_address TEXT, supplier_city VARCHAR(100), supplier_zip VARCHAR(10), supplier_country VARCHAR(100) DEFAULT 'Česká republika', -- Supplier bank information bank_name VARCHAR(255), bank_account VARCHAR(50), bank_iban VARCHAR(50), bank_swift VARCHAR(20), -- Customer information customer_id INTEGER REFERENCES invoice_customers(id), customer_name VARCHAR(255) NOT NULL, customer_ico VARCHAR(20), customer_dic VARCHAR(20), customer_address TEXT, customer_city VARCHAR(100), customer_zip VARCHAR(10), customer_country VARCHAR(100) DEFAULT 'Česká republika', customer_email VARCHAR(255), customer_phone VARCHAR(50), -- Financial summary total_amount DECIMAL(15,2) NOT NULL, total_vat DECIMAL(15,2) NOT NULL, total_amount_vat DECIMAL(15,2) NOT NULL, total_amount_without_vat DECIMAL(15,2) NOT NULL, currency VARCHAR(3) DEFAULT 'CZK', -- Status and workflow status VARCHAR(20) DEFAULT 'draft', payment_status VARCHAR(20) DEFAULT 'unpaid', payment_date TIMESTAMP, paid_amount DECIMAL(15,2) DEFAULT 0, -- Additional information note TEXT, payment_note TEXT, internal_note TEXT, -- PDF and sending pdf_path VARCHAR(500), pdf_generated_at TIMESTAMP, sent_at TIMESTAMP, sent_to TEXT, -- Metadata created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_by INTEGER, updated_by INTEGER ); CREATE INDEX idx_invoices_invoice_number ON invoices(invoice_number); CREATE INDEX idx_invoices_status ON invoices(status); CREATE INDEX idx_invoices_payment_status ON invoices(payment_status); CREATE INDEX idx_invoices_customer_id ON invoices(customer_id); CREATE INDEX idx_invoices_issue_date ON invoices(issue_date); CREATE INDEX idx_invoices_due_date ON invoices(due_date); CREATE INDEX idx_invoices_customer_ico ON invoices(customer_ico); -- Invoice items table CREATE TABLE invoice_items ( id SERIAL PRIMARY KEY, invoice_id INTEGER NOT NULL REFERENCES invoices(id) ON DELETE CASCADE, description TEXT NOT NULL, quantity DECIMAL(12,3) NOT NULL, unit VARCHAR(20) DEFAULT 'ks', unit_price DECIMAL(15,2) NOT NULL, total_price DECIMAL(15,2) NOT NULL, vat_rate DECIMAL(5,2) NOT NULL, vat_amount DECIMAL(15,2) NOT NULL, total_with_vat DECIMAL(15,2) NOT NULL, code VARCHAR(100), note TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX idx_invoice_items_invoice_id ON invoice_items(invoice_id); -- Invoice payments table CREATE TABLE invoice_payments ( id SERIAL PRIMARY KEY, invoice_id INTEGER NOT NULL REFERENCES invoices(id) ON DELETE CASCADE, amount DECIMAL(15,2) NOT NULL, currency VARCHAR(3) DEFAULT 'CZK', payment_date TIMESTAMP NOT NULL, payment_method VARCHAR(50), variable_symbol VARCHAR(20), constant_symbol VARCHAR(20), specific_symbol VARCHAR(20), bank_account VARCHAR(50), note TEXT, reference_number VARCHAR(255), created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, created_by INTEGER ); CREATE INDEX idx_invoice_payments_invoice_id ON invoice_payments(invoice_id); CREATE INDEX idx_invoice_payments_payment_date ON invoice_payments(payment_date); -- Insert default invoice settings INSERT INTO invoice_settings ( company_name, company_ico, company_dic, company_address, company_city, company_zip, company_country, bank_name, bank_account, bank_iban, bank_swift, invoice_number_format, next_invoice_number, current_year, default_payment_term, default_vat_rate, default_currency, email_subject, registration_number, tax_registration_number ) VALUES ( 'Fotbalový klub', '12345678', 'CZ12345678', 'Sportovní 1', 'Praha', '11000', 'Česká republika', 'Česká spořitelna', '123456789/0800', 'CZ650800000000123456789', 'GIBACZPX', 'F{year}{seq:6}', 1, EXTRACT(YEAR FROM CURRENT_DATE)::INTEGER, 14, 21.0, 'CZK', 'Faktura č. {invoice_number}', 'Spisová značka: 12345', 'DIČ: CZ12345678' ); -- Insert default invoice template INSERT INTO invoice_templates ( name, type, description, header_html, body_html, footer_html, css, default_vat_rate, default_payment_term, active, default ) VALUES ( 'Standardní faktura', 'standard', 'Standardní šablona pro faktury', '

{supplier_name}

{supplier_address}

{supplier_zip} {supplier_city}

IČO: {supplier_ico}

{supplier_dic ? `

DIČ: {supplier_dic}

` : ''}

Faktura

Číslo: {invoice_number}

Datum vydání: {issue_date}

Datum splatnosti: {due_date}

Datum zdanitelného plnění: {taxable_supply_date}

', '

Odběratel

{customer_name}

{customer_ico ? `

IČO: {customer_ico}

` : ''} {customer_dic ? `

DIČ: {customer_dic}

` : ''}

{customer_address}

{customer_zip} {customer_city}

{customer_country !== 'Česká republika' ? `

{customer_country}

` : ''}
{items}
Položka Množství Jedn. cena DPH % Celkem
Celkem bez DPH: {total_amount_without_vat}
DPH {total_vat_rate}%: {total_vat}
Celkem k úhradě: {total_amount_vat}
', '', 'body { font-family: Arial, sans-serif; margin: 0; padding: 20px; } .invoice-header { display: flex; justify-content: space-between; margin-bottom: 40px; } .logo img { max-height: 80px; } .invoice-info { text-align: right; } .invoice-info h1 { margin: 0; font-size: 24px; } .invoice-body { margin-bottom: 40px; } .customer-info { margin-bottom: 30px; } .invoice-items table { width: 100%; border-collapse: collapse; margin-bottom: 20px; } .invoice-items th, .invoice-items td { border: 1px solid #ddd; padding: 8px; text-align: left; } .invoice-items th { background-color: #f5f5f5; } .invoice-items .amount { text-align: right; } .invoice-summary table { width: 300px; margin-left: auto; } .invoice-summary td { padding: 5px; } .invoice-summary .total { font-weight: bold; border-top: 2px solid #333; } .invoice-footer { margin-top: 40px; } .payment-info { margin-bottom: 20px; } .signature-line { border-bottom: 1px solid #333; width: 200px; margin-top: 40px; }', 21.0, 14, true, true ); -- Create trigger to update updated_at column CREATE OR REPLACE FUNCTION update_updated_at_column() RETURNS TRIGGER AS $$ BEGIN NEW.updated_at = CURRENT_TIMESTAMP; RETURN NEW; END; $$ language 'plpgsql'; -- Apply the trigger to all invoice tables CREATE TRIGGER update_invoice_settings_updated_at BEFORE UPDATE ON invoice_settings FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_invoice_customers_updated_at BEFORE UPDATE ON invoice_customers FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_invoice_sequences_updated_at BEFORE UPDATE ON invoice_sequences FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_invoice_templates_updated_at BEFORE UPDATE ON invoice_templates FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_invoices_updated_at BEFORE UPDATE ON invoices FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_invoice_items_updated_at BEFORE UPDATE ON invoice_items FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); CREATE TRIGGER update_invoice_payments_updated_at BEFORE UPDATE ON invoice_payments FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();