From 147451c2592293fe9c8201e13994085d288f44ed Mon Sep 17 00:00:00 2001 From: Christian Date: Tue, 25 Aug 2026 06:43:31 +0200 Subject: [PATCH] release: v2.6.1 --- MDfile/RELEASE_NOTES_v2.6.1.md | 21 ++++++++++ VERSION | 2 +- migrations/006_settings.sql | 1 + migrations/026_ticket_enhancements.sql | 6 +++ .../108_add_product_id_to_sag_salgsvarer.sql | 38 +++++++++++++++++++ migrations/999_fix_cvr_unique_constraint.sql | 19 ++++++---- 6 files changed, 78 insertions(+), 9 deletions(-) create mode 100644 MDfile/RELEASE_NOTES_v2.6.1.md diff --git a/MDfile/RELEASE_NOTES_v2.6.1.md b/MDfile/RELEASE_NOTES_v2.6.1.md new file mode 100644 index 0000000..71a3f53 --- /dev/null +++ b/MDfile/RELEASE_NOTES_v2.6.1.md @@ -0,0 +1,21 @@ +# Release Notes: v2.6.1 + +**Dato:** 25. august 2026 + +## Overblik + +Version 2.6.1 retter genkørsel af fem ældre migrationer, som produktionsserverens schema-detektion korrekt fandt, men som ikke var fuldt idempotente. + +## Databasemigrationer + +- Settings- og ticket-triggers fjernes sikkert, før de genoprettes. +- `sag_salgsvarer` oprettes fra rod-migrationerne, hvis den modul-lokale grundmigration ikke tidligere er kørt. +- Produkt-, leverandørfaktura- og sporbarhedskolonner kan derefter tilføjes sikkert. +- Ticket-views med udvidede tabelkolonner genskabes sikkert ved genkørsel. +- Den forældede unikke CVR-regel er fjernet i overensstemmelse med den nuværende datamodel, hvor flere kundeposter må dele CVR-nummer. + +## Verifikation + +- De fem berørte migrationer er kørt samlet mod lokal PostgreSQL: **5 bestået**. +- Hele sættet er derefter genkørt: **5 bestået**, hvilket bekræfter idempotens. +- Diff-kontrol er gennemført. diff --git a/VERSION b/VERSION index e70b452..6a6a3d8 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.6.0 +2.6.1 diff --git a/migrations/006_settings.sql b/migrations/006_settings.sql index 5a8b894..e749098 100644 --- a/migrations/006_settings.sql +++ b/migrations/006_settings.sql @@ -65,6 +65,7 @@ BEGIN END; $$ LANGUAGE plpgsql; +DROP TRIGGER IF EXISTS settings_updated_at_trigger ON settings; CREATE TRIGGER settings_updated_at_trigger BEFORE UPDATE ON settings FOR EACH ROW diff --git a/migrations/026_ticket_enhancements.sql b/migrations/026_ticket_enhancements.sql index 33cec61..d84e32a 100644 --- a/migrations/026_ticket_enhancements.sql +++ b/migrations/026_ticket_enhancements.sql @@ -313,6 +313,7 @@ BEGIN END; $$ LANGUAGE plpgsql; +DROP TRIGGER IF EXISTS tticket_audit_changes ON tticket_tickets; CREATE TRIGGER tticket_audit_changes AFTER UPDATE ON tticket_tickets FOR EACH ROW @@ -323,6 +324,9 @@ CREATE TRIGGER tticket_audit_changes -- ============================================================================ -- View for tickets with hierarchy info +-- The view contains t.*, so later columns on tticket_tickets can shift the +-- expanded output. PostgreSQL cannot reconcile that with CREATE OR REPLACE. +DROP VIEW IF EXISTS tticket_tickets_with_hierarchy; CREATE OR REPLACE VIEW tticket_tickets_with_hierarchy AS SELECT t.*, @@ -334,6 +338,7 @@ FROM tticket_tickets t LEFT JOIN tticket_tickets parent ON t.parent_ticket_id = parent.id; -- View for tickets with pending AI suggestions +DROP VIEW IF EXISTS tticket_tickets_with_suggestions; CREATE OR REPLACE VIEW tticket_tickets_with_suggestions AS SELECT t.id, @@ -348,6 +353,7 @@ LEFT JOIN tticket_calendar_events ce ON t.id = ce.ticket_id GROUP BY t.id, t.ticket_number, t.subject, t.status; -- View for overdue tickets +DROP VIEW IF EXISTS tticket_overdue_tickets; CREATE OR REPLACE VIEW tticket_overdue_tickets AS SELECT t.id, diff --git a/migrations/108_add_product_id_to_sag_salgsvarer.sql b/migrations/108_add_product_id_to_sag_salgsvarer.sql index f0ddbde..b04ed41 100644 --- a/migrations/108_add_product_id_to_sag_salgsvarer.sql +++ b/migrations/108_add_product_id_to_sag_salgsvarer.sql @@ -1,5 +1,43 @@ -- Migration 108: Add product_id to sag_salgsvarer +-- Some installations only execute migrations from the root migrations folder. +-- Bootstrap the module table here when the earlier module-local migration has +-- not been run. All statements remain safe when the table already exists. +CREATE TABLE IF NOT EXISTS sag_salgsvarer ( + id SERIAL PRIMARY KEY, + sag_id INTEGER NOT NULL REFERENCES sag_sager(id) ON DELETE CASCADE, + type VARCHAR(20) NOT NULL DEFAULT 'sale', + description TEXT NOT NULL, + quantity NUMERIC(12, 2), + unit VARCHAR(50), + unit_price NUMERIC(12, 2), + amount NUMERIC(12, 2) NOT NULL, + currency VARCHAR(10) NOT NULL DEFAULT 'DKK', + status VARCHAR(20) NOT NULL DEFAULT 'draft', + line_date DATE, + external_ref VARCHAR(100), + created_at TIMESTAMP NOT NULL DEFAULT NOW(), + updated_at TIMESTAMP NOT NULL DEFAULT NOW() +); + +CREATE INDEX IF NOT EXISTS idx_sag_salgsvarer_sag_id ON sag_salgsvarer(sag_id); +CREATE INDEX IF NOT EXISTS idx_sag_salgsvarer_type ON sag_salgsvarer(type); +CREATE INDEX IF NOT EXISTS idx_sag_salgsvarer_status ON sag_salgsvarer(status); + +CREATE OR REPLACE FUNCTION update_sag_salgsvarer_updated_at() +RETURNS TRIGGER AS $$ +BEGIN + NEW.updated_at = NOW(); + RETURN NEW; +END; +$$ LANGUAGE plpgsql; + +DROP TRIGGER IF EXISTS trigger_sag_salgsvarer_updated_at ON sag_salgsvarer; +CREATE TRIGGER trigger_sag_salgsvarer_updated_at +BEFORE UPDATE ON sag_salgsvarer +FOR EACH ROW +EXECUTE FUNCTION update_sag_salgsvarer_updated_at(); + ALTER TABLE sag_salgsvarer ADD COLUMN IF NOT EXISTS product_id INTEGER REFERENCES products(id); diff --git a/migrations/999_fix_cvr_unique_constraint.sql b/migrations/999_fix_cvr_unique_constraint.sql index a15027f..fce0a57 100644 --- a/migrations/999_fix_cvr_unique_constraint.sql +++ b/migrations/999_fix_cvr_unique_constraint.sql @@ -1,13 +1,16 @@ --- Migration: Fix CVR Unique Constraint --- Allow multiple customers without CVR number (NULL or empty string) +-- Migration: Remove the legacy CVR uniqueness rule. +-- CVR is company metadata and multiple e-conomic customer records may +-- legitimately share the same value. This mirrors migration 1000 and keeps +-- this historical migration safe when schema detection selects it again. -- Drop old unique constraint ALTER TABLE customers DROP CONSTRAINT IF EXISTS customers_cvr_number_key; --- Create partial unique index - only enforce uniqueness for non-empty CVR numbers -CREATE UNIQUE INDEX IF NOT EXISTS customers_cvr_number_unique_idx -ON customers (cvr_number) -WHERE cvr_number IS NOT NULL AND cvr_number != ''; +DROP INDEX IF EXISTS customers_cvr_number_unique_idx; -COMMENT ON INDEX customers_cvr_number_unique_idx IS -'Ensures CVR numbers are unique, but allows multiple customers without CVR'; +CREATE INDEX IF NOT EXISTS idx_customers_cvr + ON customers(cvr_number) + WHERE cvr_number IS NOT NULL AND cvr_number <> ''; + +COMMENT ON COLUMN customers.cvr_number IS + 'Danish CVR number. Informational/searchable; duplicates are allowed.';