fix(vehicles): canonicalise brand casing (case-insensitive brand match)

Decode persist looked brands up with a case-sensitive eq(), so an
uppercase decode string ("FORD") missed canonical "Ford" → brand_id
NULL + raw uppercase stored as brand_name, splitting one brand across
casing variants in analytics/catalog. Now matches brands
case-insensitively and stores the canonical name. Migration
0013_fix_brand_casing backfills existing rows (60 on prod, 1 on dev).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-09 23:47:33 +03:00
parent 597391bbdf
commit f955bb7ef8
3 changed files with 43 additions and 2 deletions

View File

@@ -0,0 +1,28 @@
-- Canonicalise vehicle brand casing + backfill missing brand_id.
--
-- Root cause: the decode persist (vehicles.service.ts) looked brands up with a
-- case-SENSITIVE `eq(brands.name, brandName)`. A decode source that yields an
-- uppercase brand string (e.g. "FORD", "MERCEDES-BENZ") missed the canonical
-- "Ford" / "Mercedes-Benz" row → brand_id stayed NULL and the raw uppercase
-- string was stored as brand_name. That split the same brand across casing
-- variants in analytics + the catalog ("Ford" vs "FORD"). The companion code
-- fix makes the lookup case-insensitive and stores the canonical name; this
-- migration repairs the rows already written.
--
-- Backfill every vehicle whose brand_name matches a canonical brand
-- case-insensitively: set the FK and the canonical-cased name. (catalog_vehicles
-- is intentionally untouched — its brand_name namespace does not match the
-- brands table, so 0 rows would qualify.)
UPDATE "vehicles" v
SET brand_id = b.id, brand_name = b.name
FROM "brands" b
WHERE v.brand_id IS NULL AND lower(v.brand_name) = lower(b.name);
--> statement-breakpoint
-- Defensive: realign any vehicle whose brand_id is set but whose denormalised
-- brand_name has drifted from the canonical brands.name (none today, but keeps
-- the FK and the denormalised name consistent going forward).
UPDATE "vehicles" v
SET brand_name = b.name
FROM "brands" b
WHERE v.brand_id = b.id AND v.brand_name <> b.name;