Files
accounted/lib/vat/__tests__/country-codes-sql-parity.test.ts
T
MattssonandClaude Fable 5.1 3159920d7c fix(customers): re-issue the country backfill skipping migration-reset source companies (#2249)
* fix(customers): re-issue the country backfill skipping migration-reset source companies

Migration 20260903170000 (PR #2241) failed on prod at its first UPDATE:
"Archived migration reset source records are immutable" (SQLSTATE P0001).
Rows of a company listed in company_migration_resets are frozen by
trigger, and the backfill touched them, so the whole file rolled back and
prod has neither normalize_country_code() nor country_raw.

The same SQL ships again as 20260903173000 with every UPDATE excluding
those companies (their legacy text keeps being read through
normalizeCountryCode() at runtime). The old file is removed rather than
edited: prod never recorded it, staging was re-tracked under the new
version by hand. References in code, tests and DECISIONS.md follow.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D5EmmndLyDCmY5NHYAvYkE

* docs(decisions): cite the shipped backfill version 20260903173000

The country-ISO entry still named 20260903170000, the version that never
landed on prod; only the follow-up entry keeps that number, as history.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D5EmmndLyDCmY5NHYAvYkE

* docs(decisions): drop the duplicate country-ISO entry the merge carried in

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D5EmmndLyDCmY5NHYAvYkE

* docs(decisions): keep a single country-ISO entry

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D5EmmndLyDCmY5NHYAvYkE

* docs(decisions): rebuild the tail from main so the merge leaves no duplicated entries

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-03 19:39:56 +02:00

44 lines
1.5 KiB
TypeScript

/**
* The backfill in migration 20260903173000 maps country names with a SQL
* function that carries its own copy of the name table. This test holds the
* two copies to each other: every name the SQL knows must map to the same
* code in TypeScript, and every name TypeScript knows must be in the SQL.
*/
import { describe, it, expect } from 'vitest'
import { readFileSync } from 'node:fs'
import { join } from 'node:path'
import { listKnownCountryNames, normalizeCountryCode } from '../country-codes'
const MIGRATION = join(
process.cwd(),
'supabase/migrations/20260903173000_customer_supplier_country_iso.sql',
)
function sqlNameTable(): Map<string, string> {
const sql = readFileSync(MIGRATION, 'utf-8')
const table = new Map<string, string>()
const re = /^\s+\('((?:[^']|'')+)', '([A-Z]{2})'\),?$/gm
for (const match of sql.matchAll(re)) {
table.set(match[1].replace(/''/g, "'"), match[2])
}
return table
}
describe('normalize_country_code() SQL table vs normalizeCountryCode()', () => {
it('maps every SQL name to the same code in TypeScript', () => {
const sql = sqlNameTable()
expect(sql.size).toBeGreaterThan(100)
for (const [name, code] of sql) {
expect(normalizeCountryCode(name), name).toBe(code)
}
})
it('carries every TypeScript name in the SQL table', () => {
const sql = sqlNameTable()
const ts = listKnownCountryNames()
const missing = ts.filter(([name, code]) => sql.get(name) !== code)
expect(missing).toEqual([])
expect(sql.size).toBe(ts.length)
})
})