feat(12-01): add migration 093 for pax8 orders + company matching schema

- Enable pg_trgm extension for fuzzy company-name matching
- Add per-company id, billing period, and dual-cost columns to pax8_order_items
- Add auto-match columns (autotask_company_id, match_confidence, match_method, matched_at) to pax8_companies
- Applied to dev DB and verified idempotent
This commit is contained in:
lorentz 2026-07-10 22:40:03 -04:00
parent f68e1c50b6
commit 111ef56e45

View file

@ -0,0 +1,64 @@
-- PAX8 orders/invoices + company matching — schema foundation (Phase 12).
--
-- Enables pg_trgm (fuzzy-name company matching, PAX8-10/PAX8-11) and closes
-- two schema gaps discovered by live PAX8 verification (12-RESEARCH.md):
--
-- 1. Invoice headers (pax8_orders) carry no per-customer data — PAX8's
-- /invoices response always returns companyId=NULL on the header; the
-- real per-company + billing-period cost data lives on each invoice
-- item instead (12-RESEARCH.md Pitfall 1). pax8_order_items therefore
-- needs its own company/period/cost columns. pax8_orders.pax8_company_id
-- will intentionally stay NULL for every real synced row — this is
-- expected PAX8 API behavior, not a sync bug.
-- 2. pax8_companies has nowhere to persist a confident auto-match against
-- an Autotask company (PAX8-10/PAX8-11).
--
-- Additive-only: every new column and index below is guarded (IF NOT EXISTS).
-- Does not edit migration 091 and does not touch pax8_orders or
-- pax8_company_match_review, which are already correctly shaped.
-- ---------------------------------------------------------------------------
-- 1. pg_trgm — trigram similarity for fuzzy company-name matching
-- ---------------------------------------------------------------------------
CREATE EXTENSION IF NOT EXISTS pg_trgm;
-- ---------------------------------------------------------------------------
-- 2. pax8_order_items — per-company id, billing period, dual-cost columns
-- ---------------------------------------------------------------------------
-- pax8_company_id / subscription_id are soft refs (plain indexed columns, no
-- hard FK) matching the pax8_subscriptions.pax8_company_id convention — sync
-- insert order across items/companies/subscriptions is not guaranteed within
-- a single pass. item_type has no CHECK constraint (free-form, matching
-- pax8_subscriptions.status) since the full set of PAX8 invoice item types
-- ('subscription' | 'prorate' | 'one-time' and possibly others) isn't fully
-- enumerated yet.
ALTER TABLE pax8_order_items ADD COLUMN IF NOT EXISTS pax8_company_id UUID; -- soft ref -> pax8_companies(id)
ALTER TABLE pax8_order_items ADD COLUMN IF NOT EXISTS subscription_id UUID; -- soft ref -> pax8_subscriptions(id)
ALTER TABLE pax8_order_items ADD COLUMN IF NOT EXISTS item_type TEXT;
ALTER TABLE pax8_order_items ADD COLUMN IF NOT EXISTS sku TEXT;
ALTER TABLE pax8_order_items ADD COLUMN IF NOT EXISTS description TEXT;
ALTER TABLE pax8_order_items ADD COLUMN IF NOT EXISTS start_period TIMESTAMPTZ;
ALTER TABLE pax8_order_items ADD COLUMN IF NOT EXISTS end_period TIMESTAMPTZ;
ALTER TABLE pax8_order_items ADD COLUMN IF NOT EXISTS partner_cost NUMERIC(12,2);
ALTER TABLE pax8_order_items ADD COLUMN IF NOT EXISTS partner_cost_total NUMERIC(12,2);
CREATE INDEX IF NOT EXISTS idx_pax8_order_items_company ON pax8_order_items(pax8_company_id);
CREATE INDEX IF NOT EXISTS idx_pax8_order_items_period ON pax8_order_items(start_period, end_period);
-- ---------------------------------------------------------------------------
-- 3. pax8_companies — auto-match columns
-- ---------------------------------------------------------------------------
-- autotask_company_id is a soft ref (no hard FK) matching the soft-ref
-- convention used elsewhere in this schema. match_confidence stores the raw
-- pg_trgm similarity score (0.000-1.000); match_method distinguishes an
-- automated pg_trgm match from a manual admin resolution recorded via
-- pax8_company_match_review.
ALTER TABLE pax8_companies ADD COLUMN IF NOT EXISTS autotask_company_id BIGINT; -- soft ref -> companies(id)
ALTER TABLE pax8_companies ADD COLUMN IF NOT EXISTS match_confidence NUMERIC(4,3);
ALTER TABLE pax8_companies ADD COLUMN IF NOT EXISTS match_method TEXT; -- 'pg_trgm' | 'manual'
ALTER TABLE pax8_companies ADD COLUMN IF NOT EXISTS matched_at TIMESTAMPTZ;
CREATE INDEX IF NOT EXISTS idx_pax8_companies_autotask ON pax8_companies(autotask_company_id);