Invoice Numbering v2

Type: service/pipeline change · Status: Phase 1+2 deployed (no cutover) · Updated: 2026-08-10

Plan (authoritative, per-item annotated): /home/claude/INVOICE_NUMBERING_V2_PLAN.md Commit: entirely-api a617620 (2026-08-10, deployed api+worker+scheduler)

What changed

  • services/invoice_ledger.py (new): Supabase-backed number allocation for the future cutover — RPC next_invoice_ordinal (advisory-locked, template-insert), seed_invoice_ledger; on 23505 the project parks in the owner review queue (confidence_routing_service.park_for_owner_review, new) + critical notification to dustin, raises InvoiceNumberingConflict. Never retry-loops.
  • services/invoice_normalize.py: now the single parser for BOTH invoice grammars (v1 [T]BRANCH-INV-#### and v2 [T-]{PID}-INV{n}/-CM{n} incl. triage T-MAN-R7877-INV1 and GW compound 196028-MAN-9042-INV1). Config-sourced tokens. Consumers: payment_reconciliation (3 sites), portal_payment_recon (_match_line_item + upload extraction). Bare-digit references now require amount corroboration (projects.invoice_total) or park as “review”.
  • services/project_id.py: next_project_seq RPC first (atomic, self-seeding; kills MAX-scan race + >1000-row page bomb), loud fallback until migration 039 applies. GW Corporate → NOR series.
  • supabase_write_service.create_project: freezes projects.branch_code at creation (config.derive_branch_code_at_creation; NULL = derive-on-read).

Pending

  • Migrations 039 (ledger/RPCs/branch_code) + 040 (unique index on projects.project_id; audit found 0 dups) NOT YET APPLIED — needs Supabase auth.
  • Dustin: /home/claude/PROJECT_ID_BACKFILL_REPORT_2026-08-10.md (4 NULL ids, 2 duplicate project rows, branch_code backfill offer).
  • Cutover blocked on: PPDR project-id convention + JES AP T- semantics.