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>
345 lines
25 KiB
PL/PgSQL
345 lines
25 KiB
PL/PgSQL
-- 066_jurisdictions_and_foreign_qual.sql
|
|
--
|
|
-- Multi-jurisdiction expansion + foreign qualification support.
|
|
--
|
|
-- Context:
|
|
-- Migration 002 seeded `state_filing_fees` with 50 US states + DC and
|
|
-- created `formation_orders` constrained to US entity types. BC has
|
|
-- been bolted on for CRTC work, but there's no unified jurisdiction
|
|
-- model and no way to order a Certificate of Authority in one or
|
|
-- more states from a formation-only OR FCC multi-state client.
|
|
--
|
|
-- This migration:
|
|
--
|
|
-- 1. Creates a unified `jurisdictions` table (all US states + DC + CA
|
|
-- provinces) with country, currency, portal URLs, and a canonical
|
|
-- entity-type catalog per jurisdiction. Acts as the single source of
|
|
-- truth read by the Python JurisdictionConfig abstraction.
|
|
-- 2. Expands `formation_orders` to accept Canadian entity types + a
|
|
-- `country` column, without breaking existing US orders.
|
|
-- 3. Adds `province` to `canada_crtc_orders` (defaulting to 'BC' for
|
|
-- all existing rows so the BC pipeline keeps working).
|
|
-- 4. Creates `foreign_qualification_registrations` tracking every
|
|
-- Certificate of Authority / Foreign Qualification filing, with a
|
|
-- lifecycle independent of formation orders (so FCC clients can
|
|
-- order bulk state registration against an already-formed entity).
|
|
-- 5. Adds convenience views for the admin dashboard.
|
|
|
|
BEGIN;
|
|
|
|
-- ──────────────────────────────────────────────────────────────────────
|
|
-- 1. Canonical jurisdiction registry
|
|
-- ──────────────────────────────────────────────────────────────────────
|
|
|
|
CREATE TABLE IF NOT EXISTS jurisdictions (
|
|
code CHAR(2) PRIMARY KEY, -- e.g. 'WY', 'BC', 'ON', 'DC'
|
|
name TEXT NOT NULL, -- 'Wyoming', 'British Columbia'
|
|
country CHAR(2) NOT NULL CHECK (country IN ('US', 'CA')),
|
|
kind TEXT NOT NULL CHECK (kind IN ('state', 'district', 'province', 'territory')),
|
|
currency CHAR(3) NOT NULL DEFAULT 'USD' CHECK (currency IN ('USD', 'CAD')),
|
|
timezone TEXT, -- 'America/Chicago' etc.
|
|
|
|
-- Portal info for formation + foreign qualification
|
|
portal_name TEXT, -- 'WYBiz', 'COLIN', 'OBR'
|
|
portal_url TEXT,
|
|
portal_login_required BOOLEAN NOT NULL DEFAULT FALSE,
|
|
|
|
-- Entity type catalog the jurisdiction recognizes — used by the
|
|
-- intake wizard to present the right options.
|
|
entity_types_json JSONB NOT NULL DEFAULT '[]'::jsonb,
|
|
-- e.g. [{"code":"llc","label":"LLC"},{"code":"corp","label":"Corporation"}]
|
|
-- [{"code":"ltd","label":"Limited Company"},{"code":"inc","label":"Incorporated"}]
|
|
|
|
-- Whether we support foreign qualification filings into this
|
|
-- jurisdiction. Independent of whether we can *form* here.
|
|
supports_foreign_qualification BOOLEAN NOT NULL DEFAULT TRUE,
|
|
foreign_qual_portal_url TEXT, -- often different endpoint
|
|
foreign_qual_requires_coa BOOLEAN NOT NULL DEFAULT TRUE,
|
|
-- Whether the jurisdiction requires a Certificate of Good Standing
|
|
-- from the home state to accompany the foreign qualification.
|
|
|
|
-- NW Registered Agent wholesale pricing (integer cents)
|
|
nwra_foreign_qual_wholesale_cents INTEGER,
|
|
|
|
-- Ops notes + audit
|
|
notes TEXT,
|
|
last_verified DATE DEFAULT CURRENT_DATE,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_jurisdictions_country ON jurisdictions(country);
|
|
CREATE INDEX IF NOT EXISTS idx_jurisdictions_kind ON jurisdictions(kind);
|
|
|
|
-- Seed US states + DC. Entity-type catalog is the same everywhere in
|
|
-- the US (LLC, C-corp, S-corp, Nonprofit, LP/LLP) — jurisdictions that
|
|
-- diverge (e.g., closely-held corp, professional corp) can override via
|
|
-- update post-seed.
|
|
INSERT INTO jurisdictions (code, name, country, kind, currency, timezone, entity_types_json, supports_foreign_qualification)
|
|
VALUES
|
|
('AL','Alabama', 'US','state','USD','America/Chicago', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('AK','Alaska', 'US','state','USD','America/Anchorage', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('AZ','Arizona', 'US','state','USD','America/Phoenix', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('AR','Arkansas', 'US','state','USD','America/Chicago', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('CA','California', 'US','state','USD','America/Los_Angeles','[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('CO','Colorado', 'US','state','USD','America/Denver', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('CT','Connecticut', 'US','state','USD','America/New_York', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('DE','Delaware', 'US','state','USD','America/New_York', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('FL','Florida', 'US','state','USD','America/New_York', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('GA','Georgia', 'US','state','USD','America/New_York', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('HI','Hawaii', 'US','state','USD','Pacific/Honolulu', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('ID','Idaho', 'US','state','USD','America/Boise', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('IL','Illinois', 'US','state','USD','America/Chicago', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('IN','Indiana', 'US','state','USD','America/Indianapolis','[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('IA','Iowa', 'US','state','USD','America/Chicago', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('KS','Kansas', 'US','state','USD','America/Chicago', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('KY','Kentucky', 'US','state','USD','America/New_York', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('LA','Louisiana', 'US','state','USD','America/Chicago', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('ME','Maine', 'US','state','USD','America/New_York', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('MD','Maryland', 'US','state','USD','America/New_York', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('MA','Massachusetts', 'US','state','USD','America/New_York', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('MI','Michigan', 'US','state','USD','America/Detroit', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('MN','Minnesota', 'US','state','USD','America/Chicago', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('MS','Mississippi', 'US','state','USD','America/Chicago', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('MO','Missouri', 'US','state','USD','America/Chicago', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('MT','Montana', 'US','state','USD','America/Denver', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('NE','Nebraska', 'US','state','USD','America/Chicago', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('NV','Nevada', 'US','state','USD','America/Los_Angeles','[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('NH','New Hampshire', 'US','state','USD','America/New_York', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('NJ','New Jersey', 'US','state','USD','America/New_York', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('NM','New Mexico', 'US','state','USD','America/Denver', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('NY','New York', 'US','state','USD','America/New_York', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('NC','North Carolina','US','state','USD','America/New_York', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('ND','North Dakota', 'US','state','USD','America/Chicago', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('OH','Ohio', 'US','state','USD','America/New_York', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('OK','Oklahoma', 'US','state','USD','America/Chicago', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('OR','Oregon', 'US','state','USD','America/Los_Angeles','[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('PA','Pennsylvania', 'US','state','USD','America/New_York', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('RI','Rhode Island', 'US','state','USD','America/New_York', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('SC','South Carolina','US','state','USD','America/New_York', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('SD','South Dakota', 'US','state','USD','America/Chicago', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('TN','Tennessee', 'US','state','USD','America/Chicago', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('TX','Texas', 'US','state','USD','America/Chicago', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('UT','Utah', 'US','state','USD','America/Denver', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('VT','Vermont', 'US','state','USD','America/New_York', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('VA','Virginia', 'US','state','USD','America/New_York', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('WA','Washington', 'US','state','USD','America/Los_Angeles','[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('WV','West Virginia', 'US','state','USD','America/New_York', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('WI','Wisconsin', 'US','state','USD','America/Chicago', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('WY','Wyoming', 'US','state','USD','America/Denver', '[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
('DC','District of Columbia','US','district','USD','America/New_York','[{"code":"llc","label":"LLC"},{"code":"corporation","label":"Corporation"},{"code":"s_corp","label":"S-Corp"}]'::jsonb, TRUE),
|
|
-- Canadian provinces: entity_types differ (ltd/inc/corp, sole prop, cooperative)
|
|
('BC','British Columbia','CA','province','CAD','America/Vancouver','[{"code":"ltd","label":"Limited Company (Ltd.)"},{"code":"inc","label":"Incorporated (Inc.)"},{"code":"corp","label":"Corporation (Corp.)"}]'::jsonb, TRUE),
|
|
('ON','Ontario', 'CA','province','CAD','America/Toronto', '[{"code":"ltd","label":"Limited Company (Ltd.)"},{"code":"inc","label":"Incorporated (Inc.)"},{"code":"corp","label":"Corporation (Corp.)"}]'::jsonb, TRUE),
|
|
('AB','Alberta', 'CA','province','CAD','America/Edmonton', '[{"code":"ltd","label":"Limited Company (Ltd.)"},{"code":"inc","label":"Incorporated (Inc.)"},{"code":"corp","label":"Corporation (Corp.)"}]'::jsonb, FALSE),
|
|
('QC','Quebec', 'CA','province','CAD','America/Montreal', '[{"code":"inc","label":"Incorporated (Inc.)"}]'::jsonb, FALSE)
|
|
ON CONFLICT (code) DO NOTHING;
|
|
|
|
-- Populate portal fields from state_filing_fees where available. This
|
|
-- keeps the two tables in sync without forcing a second seed pass.
|
|
UPDATE jurisdictions j
|
|
SET portal_name = f.portal_name,
|
|
portal_url = f.portal_url
|
|
FROM state_filing_fees f
|
|
WHERE j.code = f.state_code
|
|
AND j.portal_name IS NULL;
|
|
|
|
-- ──────────────────────────────────────────────────────────────────────
|
|
-- 2. formation_orders: expand entity_type + add country
|
|
-- ──────────────────────────────────────────────────────────────────────
|
|
|
|
ALTER TABLE formation_orders
|
|
ADD COLUMN IF NOT EXISTS country CHAR(2) NOT NULL DEFAULT 'US'
|
|
CHECK (country IN ('US', 'CA'));
|
|
|
|
-- Drop the old entity_type CHECK (which limited us to LLC/corp/s_corp)
|
|
-- and replace with one that allows Canadian types. Keep the data — no
|
|
-- rewrites.
|
|
ALTER TABLE formation_orders
|
|
DROP CONSTRAINT IF EXISTS formation_orders_entity_type_check;
|
|
|
|
ALTER TABLE formation_orders
|
|
ADD CONSTRAINT formation_orders_entity_type_check
|
|
CHECK (entity_type IN (
|
|
'llc', 'corporation', 's_corp', 'c_corp', 'nonprofit',
|
|
'ltd', 'inc', 'corp', -- Canadian
|
|
'lp', 'llp', -- partnerships
|
|
'pllc', 'pc' -- professional
|
|
));
|
|
|
|
-- Convenience: derive country from jurisdictions when a row is inserted
|
|
-- without an explicit country (backfill support).
|
|
UPDATE formation_orders
|
|
SET country = COALESCE(j.country, 'US')
|
|
FROM jurisdictions j
|
|
WHERE formation_orders.state_code = j.code
|
|
AND formation_orders.country = 'US'; -- only touch default rows
|
|
|
|
-- ──────────────────────────────────────────────────────────────────────
|
|
-- 3. canada_crtc_orders: province column
|
|
-- ──────────────────────────────────────────────────────────────────────
|
|
|
|
ALTER TABLE canada_crtc_orders
|
|
ADD COLUMN IF NOT EXISTS province CHAR(2) NOT NULL DEFAULT 'BC'
|
|
CHECK (province IN ('BC','ON','AB','QC','MB','SK','NS','NB','NL','PE'));
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_canada_crtc_orders_province
|
|
ON canada_crtc_orders(province);
|
|
|
|
-- ──────────────────────────────────────────────────────────────────────
|
|
-- 4. foreign_qualification_registrations
|
|
-- ──────────────────────────────────────────────────────────────────────
|
|
--
|
|
-- A foreign qualification (aka "Certificate of Authority") is what a
|
|
-- company formed in State A files in State B to be allowed to do
|
|
-- business in State B. FCC carriers typically need one per state they
|
|
-- serve; regular formation clients may add a few as an expansion.
|
|
--
|
|
-- This table tracks each per-state filing as its own lifecycle, but all
|
|
-- filings for one order share a single parent compliance_orders row.
|
|
-- That way a 20-state FCC order is one checkout + one invoice with 20
|
|
-- independent filings + state fee obligations.
|
|
--
|
|
-- Why not reuse formation_orders: formation_orders is scoped to creating
|
|
-- a NEW entity; foreign qualification operates on an EXISTING entity.
|
|
-- Different schema (no entity_name_alt, no members, etc.), different
|
|
-- lifecycle.
|
|
|
|
CREATE TABLE IF NOT EXISTS foreign_qualification_registrations (
|
|
id BIGSERIAL PRIMARY KEY,
|
|
|
|
-- Parent order (compliance_orders row; one order can fan out to
|
|
-- many states).
|
|
compliance_order_id INTEGER REFERENCES compliance_orders(id) ON DELETE SET NULL,
|
|
order_number TEXT NOT NULL,
|
|
|
|
-- Linked existing entity (if ordered on an already-registered
|
|
-- carrier). For FCC clients this is telecom_entities.id. For
|
|
-- non-FCC formation expansion, nullable with legal_name /
|
|
-- home_state_code filled in directly.
|
|
telecom_entity_id INTEGER, -- FK enforced softly via app logic
|
|
|
|
-- Source / home jurisdiction — where the entity was originally formed.
|
|
home_country CHAR(2) NOT NULL DEFAULT 'US'
|
|
CHECK (home_country IN ('US','CA')),
|
|
home_state_code CHAR(2) NOT NULL,
|
|
|
|
-- Target jurisdiction — where we're filing the COA.
|
|
target_state_code CHAR(2) NOT NULL,
|
|
|
|
-- Entity info captured at order time. We don't trust telecom_entities
|
|
-- to be complete so we snapshot it here, mirroring how compliance
|
|
-- orders snapshot legal_name / address.
|
|
entity_legal_name TEXT NOT NULL,
|
|
entity_type TEXT NOT NULL, -- 'llc' | 'corporation' | etc.
|
|
formed_on DATE, -- original formation date
|
|
home_state_filing_number TEXT, -- original charter #
|
|
ein TEXT,
|
|
|
|
-- Principal + target-state address
|
|
principal_address_json JSONB, -- {street, city, state, zip}
|
|
registered_agent_name TEXT, -- RA in the TARGET state
|
|
registered_agent_address_json JSONB,
|
|
include_ra_service BOOLEAN NOT NULL DEFAULT TRUE,
|
|
-- NWRA provisioning — we resell their address as RA-in-target-state.
|
|
|
|
-- Money. Cents convention — target state fee + service fee + NWRA
|
|
-- wholesale cost; retail_total_cents matches the compliance_order
|
|
-- line for this state.
|
|
state_fee_cents INTEGER NOT NULL DEFAULT 0,
|
|
expedited BOOLEAN NOT NULL DEFAULT FALSE,
|
|
expedited_fee_cents INTEGER NOT NULL DEFAULT 0,
|
|
nwra_wholesale_cents INTEGER NOT NULL DEFAULT 0,
|
|
service_fee_cents INTEGER NOT NULL DEFAULT 0,
|
|
retail_total_cents INTEGER NOT NULL DEFAULT 0,
|
|
|
|
-- Documents required for the target state's filing (varies widely):
|
|
-- good_standing: certificate of good standing from home state
|
|
-- articles: articles of incorporation from home state
|
|
-- name_reservation: if target state requires one
|
|
-- publication: e.g. NY, AZ, NE require newspaper publication
|
|
supporting_docs_json JSONB NOT NULL DEFAULT '{}'::jsonb,
|
|
|
|
-- Pipeline state per filing.
|
|
status TEXT NOT NULL DEFAULT 'received' CHECK (status IN (
|
|
'received', -- paid, queued
|
|
'docs_pending', -- waiting on good-standing cert
|
|
'filing', -- portal automation running
|
|
'admin_review', -- manual step needed
|
|
'submitted', -- filed, awaiting state approval
|
|
'approved', -- COA issued
|
|
'rejected',
|
|
'cancelled'
|
|
)),
|
|
state_filing_number TEXT, -- returned by portal
|
|
state_confirmation_url TEXT,
|
|
filed_at TIMESTAMPTZ,
|
|
approved_at TIMESTAMPTZ,
|
|
coa_minio_path TEXT, -- stored Certificate of Authority
|
|
|
|
-- Errors + ops
|
|
last_error TEXT,
|
|
attempt_count INTEGER NOT NULL DEFAULT 0,
|
|
admin_todo_id INTEGER, -- ERPNext ToDo if manual
|
|
|
|
notes TEXT,
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
|
|
-- A carrier only needs ONE active foreign qualification per target
|
|
-- state — we don't want to accept a duplicate order. Application
|
|
-- should look for WHERE status NOT IN ('cancelled','rejected').
|
|
UNIQUE (telecom_entity_id, target_state_code,
|
|
order_number) -- order_number breaks ties for re-orders
|
|
);
|
|
|
|
CREATE INDEX IF NOT EXISTS idx_fq_order_number
|
|
ON foreign_qualification_registrations(order_number);
|
|
CREATE INDEX IF NOT EXISTS idx_fq_target_state
|
|
ON foreign_qualification_registrations(target_state_code);
|
|
CREATE INDEX IF NOT EXISTS idx_fq_status
|
|
ON foreign_qualification_registrations(status)
|
|
WHERE status NOT IN ('approved','cancelled','rejected');
|
|
CREATE INDEX IF NOT EXISTS idx_fq_telecom_entity
|
|
ON foreign_qualification_registrations(telecom_entity_id)
|
|
WHERE telecom_entity_id IS NOT NULL;
|
|
|
|
-- Updated_at trigger — keep it in sync with the pattern used elsewhere.
|
|
-- We add a dedicated trigger function if one doesn't exist already.
|
|
CREATE OR REPLACE FUNCTION set_updated_at_fq() RETURNS trigger AS $$
|
|
BEGIN
|
|
NEW.updated_at = NOW();
|
|
RETURN NEW;
|
|
END;
|
|
$$ LANGUAGE plpgsql;
|
|
|
|
DROP TRIGGER IF EXISTS trg_fq_updated_at ON foreign_qualification_registrations;
|
|
CREATE TRIGGER trg_fq_updated_at
|
|
BEFORE UPDATE ON foreign_qualification_registrations
|
|
FOR EACH ROW EXECUTE FUNCTION set_updated_at_fq();
|
|
|
|
-- ──────────────────────────────────────────────────────────────────────
|
|
-- 5. View: admin dashboard pipeline
|
|
-- ──────────────────────────────────────────────────────────────────────
|
|
|
|
CREATE OR REPLACE VIEW v_foreign_qualifications_pipeline AS
|
|
SELECT
|
|
fq.id,
|
|
fq.order_number,
|
|
fq.entity_legal_name,
|
|
fq.home_state_code,
|
|
fq.target_state_code,
|
|
j.name AS target_state_name,
|
|
fq.entity_type,
|
|
fq.status,
|
|
fq.filed_at,
|
|
fq.approved_at,
|
|
fq.retail_total_cents,
|
|
fq.attempt_count,
|
|
fq.last_error,
|
|
fq.created_at
|
|
FROM foreign_qualification_registrations fq
|
|
LEFT JOIN jurisdictions j ON j.code = fq.target_state_code
|
|
ORDER BY fq.created_at DESC;
|
|
|
|
COMMIT;
|