new-site/api/migrations/056_icc_revenue.sql
justin f8cd37ac8c Initial commit — Performance West telecom compliance platform
Includes: API (Express/TypeScript), Astro site, Python workers,
document generators, FCC compliance tools, Canada CRTC formation,
Ansible infrastructure, and deployment scripts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-27 06:54:22 -05:00

130 lines
6.3 KiB
SQL

-- 056: Inter-Carrier Compensation revenue import
--
-- Post-2011 USF/ICC Transformation Order most intrastate/interstate access
-- is bill-and-keep at $0.0007/min or $0. But real money still flows in:
-- 8YY originating access ($0.002-0.005/MOU), special access / BDS,
-- international settlements, wholesale SIP trunking, access stimulation.
--
-- These revenues belong on 499-A Lines 303, 404.x, 418 depending on
-- category. icc_499a_line_mapping captures the mapping.
--
-- Pipeline mirrors the CDR ingestion pattern:
-- customer uploads file → MinIO → icc_ingester worker → adapter →
-- icc_revenue_lines (deduped by natural_key_hash) → RevenueStep
-- prefills 499-A revenue lines.
-- ── Ingestion uploads (one row per uploaded file) ───────────────────────
CREATE TABLE IF NOT EXISTS icc_ingestion_uploads (
id BIGSERIAL PRIMARY KEY,
profile_id INTEGER NOT NULL REFERENCES cdr_ingestion_profiles(id)
ON DELETE CASCADE,
customer_id INTEGER NOT NULL REFERENCES customers(id),
source_format TEXT NOT NULL CHECK (source_format IN (
'cabs_bos', -- Bellcore Billing Output Specification (fixed-width)
'edi_810', -- X12 EDI 810 invoice
'8yy_qry', -- iconectiv 8YY Query Report (XML)
'itu_tas', -- ITU Telecommunications Accounting System
'icss', -- International Carrier Settlement System
'wholesale_sip_csv', -- Sangoma / Bandwidth / Flowroute / generic CSV
'carrier_invoice_pdf' -- pdfplumber stub (LLM tagging v2)
)),
raw_minio_path TEXT NOT NULL,
raw_sha256 TEXT NOT NULL UNIQUE,
rows_accepted INTEGER DEFAULT 0,
rows_rejected INTEGER DEFAULT 0,
status TEXT NOT NULL DEFAULT 'pending'
CHECK (status IN ('pending','parsing','complete','failed')),
error_message TEXT,
summary_json JSONB, -- per-adapter details (counterparties, totals)
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
parsed_at TIMESTAMPTZ
);
CREATE INDEX IF NOT EXISTS idx_icc_uploads_profile_status
ON icc_ingestion_uploads (profile_id, status, created_at DESC);
CREATE INDEX IF NOT EXISTS idx_icc_uploads_pending
ON icc_ingestion_uploads (created_at)
WHERE status = 'pending';
-- ── Parsed revenue lines (one row per invoice line item) ────────────────
CREATE TABLE IF NOT EXISTS icc_revenue_lines (
id BIGSERIAL PRIMARY KEY,
profile_id INTEGER NOT NULL REFERENCES cdr_ingestion_profiles(id)
ON DELETE CASCADE,
reporting_year INTEGER NOT NULL,
reporting_quarter INTEGER CHECK (reporting_quarter IS NULL OR reporting_quarter BETWEEN 1 AND 4),
icc_category TEXT NOT NULL CHECK (icc_category IN (
'term_switched_access', -- terminating switched access (mostly bill-and-keep)
'orig_switched_access', -- originating switched access (billable)
'8yy_orig_access', -- 8YY originating access (iconectiv)
'transit', -- transit compensation
'special_access', -- special access / BDS (DS-1/DS-3/Ethernet carrier-to-carrier)
'intl_settlement', -- international carrier settlements
'wholesale_sip', -- wholesale SIP trunking
'access_stim', -- access stimulation (47 CFR 61.3(bbb))
'other'
)),
counterparty_legal_name TEXT,
counterparty_ocn TEXT, -- Operating Company Number
counterparty_country CHAR(2) NOT NULL DEFAULT 'US',
revenue_cents BIGINT NOT NULL, -- signed; negative = we owe them
minutes_of_use BIGINT,
source_upload_id BIGINT NOT NULL REFERENCES icc_ingestion_uploads(id)
ON DELETE CASCADE,
source_line_no INTEGER,
-- Dedup key — sha256(category|counterparty|period|amount|MOU)
natural_key_hash TEXT NOT NULL,
raw_row JSONB, -- whatever the adapter captured
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
UNIQUE (profile_id, reporting_year, reporting_quarter, natural_key_hash)
);
CREATE INDEX IF NOT EXISTS idx_icc_lines_profile_year_cat
ON icc_revenue_lines (profile_id, reporting_year, icc_category);
CREATE INDEX IF NOT EXISTS idx_icc_lines_counterparty
ON icc_revenue_lines (counterparty_ocn, reporting_year)
WHERE counterparty_ocn IS NOT NULL;
-- ── ICC category → Form 499-A line mapping ──────────────────────────────
-- Consumed by RevenueStep prefill and form_499a.py LINE_FILL_MAP.
CREATE TABLE IF NOT EXISTS icc_499a_line_mapping (
icc_category TEXT PRIMARY KEY,
form_499a_line TEXT NOT NULL, -- '404', '404.1', '404.3', '418'
jurisdiction_split TEXT NOT NULL -- 'interstate' | 'intrastate' | 'international' | 'split_traffic'
CHECK (jurisdiction_split IN (
'interstate','intrastate','international','split_traffic'
))
);
INSERT INTO icc_499a_line_mapping VALUES
('term_switched_access', '404', 'split_traffic'),
('orig_switched_access', '404', 'split_traffic'),
('8yy_orig_access', '404.3', 'interstate'),
('transit', '404', 'split_traffic'),
('special_access', '404.1', 'split_traffic'),
('intl_settlement', '418', 'international'),
('wholesale_sip', '404', 'split_traffic'),
('access_stim', '404', 'split_traffic'),
('other', '418', 'split_traffic')
ON CONFLICT (icc_category) DO NOTHING;
-- ── Access-stimulation flag on CDR profile ──────────────────────────────
-- Set by scripts/workers/access_stim_monitor.py when the rolling 6-month
-- terminating:originating MOU ratio exceeds 3:1 (47 CFR 61.3(bbb) trigger).
ALTER TABLE cdr_ingestion_profiles
ADD COLUMN IF NOT EXISTS access_stim_flagged_at TIMESTAMPTZ;
ALTER TABLE cdr_ingestion_profiles
ADD COLUMN IF NOT EXISTS access_stim_evidence_json JSONB;