-- Meshkee CMS — full invoice templates + invoice key points / accounts -- --------------------------------------------------------------------------- -- invoice templates (full blueprint: name, top text, items, key points, accounts) -- --------------------------------------------------------------------------- CREATE TABLE invoice_templates ( id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, owner_scope invoice_owner_scope NOT NULL, business_id BIGINT, name VARCHAR(255) NOT NULL, top_text TEXT, sort_order INT NOT NULL DEFAULT 0, is_active BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), CONSTRAINT invoice_templates_business_id_fkey FOREIGN KEY (business_id) REFERENCES businesses (id) ON DELETE CASCADE, CONSTRAINT invoice_templates_name_nonempty CHECK (char_length(trim(name)) > 0), CONSTRAINT invoice_templates_scope_business_check CHECK ( (owner_scope = 'platform' AND business_id IS NULL) OR (owner_scope = 'business' AND business_id IS NOT NULL) ) ); CREATE INDEX idx_invoice_templates_owner_scope ON invoice_templates (owner_scope, sort_order); CREATE INDEX idx_invoice_templates_business_id ON invoice_templates (business_id, sort_order) WHERE business_id IS NOT NULL; CREATE TRIGGER invoice_templates_set_updated_at BEFORE UPDATE ON invoice_templates FOR EACH ROW EXECUTE FUNCTION set_updated_at(); -- --------------------------------------------------------------------------- -- template line items -- --------------------------------------------------------------------------- CREATE TABLE invoice_template_items ( id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, template_id BIGINT NOT NULL, item_template_id BIGINT, title VARCHAR(255) NOT NULL, duration VARCHAR(100), worktime VARCHAR(100), description TEXT, price NUMERIC(12, 2) NOT NULL DEFAULT 0, discounted_price NUMERIC(12, 2), sort_order INT NOT NULL DEFAULT 0, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), CONSTRAINT invoice_template_items_template_id_fkey FOREIGN KEY (template_id) REFERENCES invoice_templates (id) ON DELETE CASCADE, CONSTRAINT invoice_template_items_item_template_id_fkey FOREIGN KEY (item_template_id) REFERENCES invoice_item_templates (id) ON DELETE SET NULL, CONSTRAINT invoice_template_items_title_nonempty CHECK (char_length(trim(title)) > 0), CONSTRAINT invoice_template_items_price_non_negative CHECK (price >= 0), CONSTRAINT invoice_template_items_discounted_non_negative CHECK (discounted_price IS NULL OR discounted_price >= 0) ); CREATE INDEX idx_invoice_template_items_template_id ON invoice_template_items (template_id, sort_order); CREATE TRIGGER invoice_template_items_set_updated_at BEFORE UPDATE ON invoice_template_items FOR EACH ROW EXECUTE FUNCTION set_updated_at(); -- --------------------------------------------------------------------------- -- template key points (duplicatable) -- --------------------------------------------------------------------------- CREATE TABLE invoice_template_key_points ( id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, template_id BIGINT NOT NULL, text TEXT NOT NULL, sort_order INT NOT NULL DEFAULT 0, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), CONSTRAINT invoice_template_key_points_template_id_fkey FOREIGN KEY (template_id) REFERENCES invoice_templates (id) ON DELETE CASCADE, CONSTRAINT invoice_template_key_points_text_nonempty CHECK (char_length(trim(text)) > 0) ); CREATE INDEX idx_invoice_template_key_points_template_id ON invoice_template_key_points (template_id, sort_order); CREATE TRIGGER invoice_template_key_points_set_updated_at BEFORE UPDATE ON invoice_template_key_points FOR EACH ROW EXECUTE FUNCTION set_updated_at(); -- --------------------------------------------------------------------------- -- template bank accounts (duplicatable) -- --------------------------------------------------------------------------- CREATE TABLE invoice_template_accounts ( id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, template_id BIGINT NOT NULL, bank_name VARCHAR(255) NOT NULL, card_number VARCHAR(64), iban VARCHAR(64), sort_order INT NOT NULL DEFAULT 0, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), CONSTRAINT invoice_template_accounts_template_id_fkey FOREIGN KEY (template_id) REFERENCES invoice_templates (id) ON DELETE CASCADE, CONSTRAINT invoice_template_accounts_bank_name_nonempty CHECK (char_length(trim(bank_name)) > 0) ); CREATE INDEX idx_invoice_template_accounts_template_id ON invoice_template_accounts (template_id, sort_order); CREATE TRIGGER invoice_template_accounts_set_updated_at BEFORE UPDATE ON invoice_template_accounts FOR EACH ROW EXECUTE FUNCTION set_updated_at(); -- --------------------------------------------------------------------------- -- extend issued invoices -- --------------------------------------------------------------------------- ALTER TABLE invoices ADD COLUMN IF NOT EXISTS top_text TEXT, ADD COLUMN IF NOT EXISTS invoice_template_id BIGINT; ALTER TABLE invoices DROP CONSTRAINT IF EXISTS invoices_invoice_template_id_fkey; ALTER TABLE invoices ADD CONSTRAINT invoices_invoice_template_id_fkey FOREIGN KEY (invoice_template_id) REFERENCES invoice_templates (id) ON DELETE SET NULL; CREATE INDEX IF NOT EXISTS idx_invoices_invoice_template_id ON invoices (invoice_template_id) WHERE invoice_template_id IS NOT NULL; CREATE TABLE invoice_key_points ( id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, invoice_id BIGINT NOT NULL, text TEXT NOT NULL, sort_order INT NOT NULL DEFAULT 0, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), CONSTRAINT invoice_key_points_invoice_id_fkey FOREIGN KEY (invoice_id) REFERENCES invoices (id) ON DELETE CASCADE, CONSTRAINT invoice_key_points_text_nonempty CHECK (char_length(trim(text)) > 0) ); CREATE INDEX idx_invoice_key_points_invoice_id ON invoice_key_points (invoice_id, sort_order); CREATE TRIGGER invoice_key_points_set_updated_at BEFORE UPDATE ON invoice_key_points FOR EACH ROW EXECUTE FUNCTION set_updated_at(); CREATE TABLE invoice_accounts ( id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, invoice_id BIGINT NOT NULL, bank_name VARCHAR(255) NOT NULL, card_number VARCHAR(64), iban VARCHAR(64), sort_order INT NOT NULL DEFAULT 0, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(), CONSTRAINT invoice_accounts_invoice_id_fkey FOREIGN KEY (invoice_id) REFERENCES invoices (id) ON DELETE CASCADE, CONSTRAINT invoice_accounts_bank_name_nonempty CHECK (char_length(trim(bank_name)) > 0) ); CREATE INDEX idx_invoice_accounts_invoice_id ON invoice_accounts (invoice_id, sort_order); CREATE TRIGGER invoice_accounts_set_updated_at BEFORE UPDATE ON invoice_accounts FOR EACH ROW EXECUTE FUNCTION set_updated_at();