chore(release): bump version to 2.3.28

This commit is contained in:
Christian 2026-07-11 10:31:20 +02:00
parent 09fef6ff8c
commit 2b4dd6b010
2 changed files with 165 additions and 1 deletions

View File

@ -1 +1 @@
2.3.27
2.3.28

View File

@ -0,0 +1,164 @@
-- Backfill invoice error finder schema on environments where module migrations
-- were not executed through the main production migration flow.
CREATE TABLE IF NOT EXISTS invoice_error_finder_import_runs (
id SERIAL PRIMARY KEY,
source_type VARCHAR(50) NOT NULL,
started_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
completed_at TIMESTAMP,
status VARCHAR(20) NOT NULL DEFAULT 'running' CHECK (status IN ('running', 'success', 'partial', 'failed')),
records_imported INTEGER NOT NULL DEFAULT 0,
records_failed INTEGER NOT NULL DEFAULT 0,
error_message TEXT,
triggered_by_user_id INTEGER REFERENCES users(user_id) ON DELETE SET NULL,
is_scheduled BOOLEAN NOT NULL DEFAULT FALSE,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_ief_import_runs_source
ON invoice_error_finder_import_runs(source_type, started_at DESC);
CREATE TABLE IF NOT EXISTS invoice_error_finder_economic_invoices (
id SERIAL PRIMARY KEY,
import_run_id INTEGER NOT NULL REFERENCES invoice_error_finder_import_runs(id) ON DELETE CASCADE,
source_invoice_number VARCHAR(80),
source_type VARCHAR(30) NOT NULL DEFAULT 'booked',
customer_number INTEGER,
customer_name VARCHAR(255),
invoice_date DATE,
due_date DATE,
currency VARCHAR(10) DEFAULT 'DKK',
net_amount NUMERIC(14,2),
vat_amount NUMERIC(14,2),
total_amount NUMERIC(14,2),
source_raw JSONB NOT NULL DEFAULT '{}'::jsonb,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT uq_ief_economic_invoice_import UNIQUE (import_run_id, source_invoice_number, source_type)
);
CREATE INDEX IF NOT EXISTS idx_ief_economic_invoices_run
ON invoice_error_finder_economic_invoices(import_run_id);
CREATE INDEX IF NOT EXISTS idx_ief_economic_invoices_customer
ON invoice_error_finder_economic_invoices(customer_number);
CREATE INDEX IF NOT EXISTS idx_ief_economic_invoices_date
ON invoice_error_finder_economic_invoices(invoice_date);
CREATE TABLE IF NOT EXISTS invoice_error_finder_economic_invoice_lines (
id SERIAL PRIMARY KEY,
invoice_id INTEGER NOT NULL REFERENCES invoice_error_finder_economic_invoices(id) ON DELETE CASCADE,
line_number INTEGER,
product_number VARCHAR(100),
product_name VARCHAR(500),
description TEXT,
quantity NUMERIC(14,4) NOT NULL DEFAULT 0,
unit_price NUMERIC(14,4) NOT NULL DEFAULT 0,
line_net_amount NUMERIC(14,2) NOT NULL DEFAULT 0,
discount_percentage NUMERIC(5,2) DEFAULT 0,
source_raw JSONB NOT NULL DEFAULT '{}'::jsonb,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_ief_economic_lines_invoice
ON invoice_error_finder_economic_invoice_lines(invoice_id);
CREATE INDEX IF NOT EXISTS idx_ief_economic_lines_product
ON invoice_error_finder_economic_invoice_lines(product_number);
CREATE TABLE IF NOT EXISTS invoice_error_finder_simply_sales_orders (
id SERIAL PRIMARY KEY,
import_run_id INTEGER NOT NULL REFERENCES invoice_error_finder_import_runs(id) ON DELETE CASCADE,
source_record_id VARCHAR(80) NOT NULL,
salesorder_no VARCHAR(80),
account_id VARCHAR(80),
customer_name VARCHAR(255),
customer_cvr VARCHAR(32),
subject TEXT,
status VARCHAR(50),
product_number VARCHAR(100),
product_name VARCHAR(500),
quantity NUMERIC(14,4) NOT NULL DEFAULT 0,
unit_price NUMERIC(14,4) NOT NULL DEFAULT 0,
total_amount NUMERIC(14,2) NOT NULL DEFAULT 0,
start_period DATE,
end_period DATE,
source_raw JSONB NOT NULL DEFAULT '{}'::jsonb,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT uq_ief_simply_order_import UNIQUE (source_record_id)
);
CREATE INDEX IF NOT EXISTS idx_ief_simply_orders_run
ON invoice_error_finder_simply_sales_orders(import_run_id);
CREATE INDEX IF NOT EXISTS idx_ief_simply_orders_account
ON invoice_error_finder_simply_sales_orders(account_id);
CREATE INDEX IF NOT EXISTS idx_ief_simply_orders_status
ON invoice_error_finder_simply_sales_orders(status);
CREATE TABLE IF NOT EXISTS invoice_error_finder_issues (
id SERIAL PRIMARY KEY,
issue_type VARCHAR(50) NOT NULL CHECK (issue_type IN (
'missing_line',
'open_order_not_invoiced',
'quantity_drop',
'price_change',
'new_item_never_invoiced'
)),
status VARCHAR(30) NOT NULL DEFAULT 'open' CHECK (status IN (
'open',
'investigating',
'approved_change',
'error_found',
'ready_to_invoice',
'invoiced',
'ignored'
)),
customer_id INTEGER REFERENCES customers(id) ON DELETE SET NULL,
customer_name VARCHAR(255),
subscription_id INTEGER REFERENCES sag_subscriptions(id) ON DELETE SET NULL,
simply_order_id INTEGER REFERENCES invoice_error_finder_simply_sales_orders(id) ON DELETE SET NULL,
simply_source_record_id VARCHAR(80),
sag_id INTEGER REFERENCES sag_sager(id) ON DELETE SET NULL,
product_number VARCHAR(100),
product_name VARCHAR(500),
reference_period_start DATE,
reference_period_end DATE,
expected_quantity NUMERIC(14,4),
actual_quantity NUMERIC(14,4),
expected_price NUMERIC(14,4),
actual_price NUMERIC(14,4),
last_invoice_number VARCHAR(80),
last_invoice_date DATE,
sales_order_number VARCHAR(80),
amount_impact NUMERIC(14,2),
currency VARCHAR(10) DEFAULT 'DKK',
assigned_user_id INTEGER REFERENCES users(user_id) ON DELETE SET NULL,
notes TEXT,
ignored_until DATE,
resolved_at TIMESTAMP,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_ief_issues_type
ON invoice_error_finder_issues(issue_type);
CREATE INDEX IF NOT EXISTS idx_ief_issues_status
ON invoice_error_finder_issues(status);
CREATE INDEX IF NOT EXISTS idx_ief_issues_customer
ON invoice_error_finder_issues(customer_id);
CREATE INDEX IF NOT EXISTS idx_ief_issues_period
ON invoice_error_finder_issues(reference_period_start, reference_period_end);
CREATE INDEX IF NOT EXISTS idx_ief_issues_assigned
ON invoice_error_finder_issues(assigned_user_id)
WHERE assigned_user_id IS NULL;
CREATE OR REPLACE FUNCTION update_ief_issues_updated_at()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = CURRENT_TIMESTAMP;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
DROP TRIGGER IF EXISTS trigger_ief_issues_updated_at ON invoice_error_finder_issues;
CREATE TRIGGER trigger_ief_issues_updated_at
BEFORE UPDATE ON invoice_error_finder_issues
FOR EACH ROW
EXECUTE FUNCTION update_ief_issues_updated_at();