-- Migration 171: Supplier invoice v2 lifecycle (status, approval, split payments, event log) -- Created: 2026-04-12 ALTER TABLE supplier_invoices ADD COLUMN IF NOT EXISTS workflow_status_v2 VARCHAR(20), ADD COLUMN IF NOT EXISTS rejected_by VARCHAR(255), ADD COLUMN IF NOT EXISTS rejected_at TIMESTAMP, ADD COLUMN IF NOT EXISTS rejection_reason TEXT, ADD COLUMN IF NOT EXISTS payment_method VARCHAR(100); DO $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM pg_constraint WHERE conname = 'chk_supplier_invoices_workflow_status_v2' ) THEN ALTER TABLE supplier_invoices ADD CONSTRAINT chk_supplier_invoices_workflow_status_v2 CHECK (workflow_status_v2 IN ('modtaget', 'godkendt', 'betalt', 'afvist')); END IF; END $$; -- Backfill v2 statuses from legacy status values. UPDATE supplier_invoices SET workflow_status_v2 = CASE WHEN status IN ('approved', 'sent_to_economic') THEN 'godkendt' WHEN status = 'paid' THEN 'betalt' WHEN status IN ('cancelled', 'credited', 'rejected') THEN 'afvist' ELSE 'modtaget' END WHERE workflow_status_v2 IS NULL; ALTER TABLE supplier_invoices ALTER COLUMN workflow_status_v2 SET DEFAULT 'modtaget'; ALTER TABLE supplier_invoices ALTER COLUMN workflow_status_v2 SET NOT NULL; CREATE INDEX IF NOT EXISTS idx_supplier_invoices_workflow_status_v2 ON supplier_invoices(workflow_status_v2); -- Split payments on supplier invoices. CREATE TABLE IF NOT EXISTS supplier_invoice_payments ( id SERIAL PRIMARY KEY, supplier_invoice_id INTEGER NOT NULL REFERENCES supplier_invoices(id) ON DELETE CASCADE, payment_date DATE NOT NULL, amount DECIMAL(15, 2) NOT NULL CHECK (amount > 0), currency VARCHAR(10) NOT NULL DEFAULT 'DKK', payment_method VARCHAR(100), payment_reference VARCHAR(100), notes TEXT, paid_by VARCHAR(255), created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ); CREATE INDEX IF NOT EXISTS idx_supplier_invoice_payments_invoice_id ON supplier_invoice_payments(supplier_invoice_id); CREATE INDEX IF NOT EXISTS idx_supplier_invoice_payments_date ON supplier_invoice_payments(payment_date); -- Event log / outbox-style table for later webhook activation. CREATE TABLE IF NOT EXISTS supplier_invoice_events ( id BIGSERIAL PRIMARY KEY, supplier_invoice_id INTEGER NOT NULL REFERENCES supplier_invoices(id) ON DELETE CASCADE, event_type VARCHAR(60) NOT NULL, from_status VARCHAR(20), to_status VARCHAR(20), payload_json JSONB NOT NULL DEFAULT '{}'::jsonb, webhook_status VARCHAR(20) NOT NULL DEFAULT 'pending', created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, processed_at TIMESTAMP ); CREATE INDEX IF NOT EXISTS idx_supplier_invoice_events_invoice_id ON supplier_invoice_events(supplier_invoice_id); CREATE INDEX IF NOT EXISTS idx_supplier_invoice_events_webhook_status ON supplier_invoice_events(webhook_status); COMMENT ON COLUMN supplier_invoices.workflow_status_v2 IS 'v2 lifecycle: modtaget, godkendt, betalt, afvist'; COMMENT ON TABLE supplier_invoice_payments IS 'Partial/split payments for supplier invoices'; COMMENT ON TABLE supplier_invoice_events IS 'Supplier invoice event log prepared for future webhook/outbox processing';