165 lines
6.5 KiB
PL/PgSQL
165 lines
6.5 KiB
PL/PgSQL
-- 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();
|