Quick lookup project for time zones.

This commit is contained in:
Scott Idem
2026-03-23 17:50:59 -04:00
parent c9ec3d7ea1
commit 15b5084df3

View File

@@ -0,0 +1,144 @@
# Project: V3 Lookup Bug Fix — Timezone Group Data + PARTITION BY Revert
> **Status:** 🔧 Action Required
> **Date:** 2026-03-23
> **Related doc:** `PROJECT__V3_UNIFORM_LOOKUP_SYSTEM.md`
> **Reported by:** Frontend Agent (Scott Idem / One Sky IT)
---
## 1. Summary
Two bugs were discovered in the V3 Uniform Lookup System during IDAA Recovery Meetings
timezone dropdown testing. They stem from a single root cause: the `lu_v3_time_zone`
table was seeded with regional `group` values (`"United States"`, `"Europe"`) instead of
individual timezone names — contrary to the design specified in Phase 2 of the lookup
architecture doc, which explicitly states `lu_v3_time_zone (Group: name)`.
An attempted fix changed `PARTITION BY group` to `PARTITION BY name` in
`get_lookup_list_v3()`. This unintentionally broke country deduplication, which depends
on `PARTITION BY group` being correct (country group = `alpha_2_code`, e.g. `"US"`).
---
## 2. Root Cause
### 2.1 Timezone `group` values were set to regional names instead of timezone names
The `lu_v3_time_zone` table has two groups where multiple records share a single group value:
| `group` value | Count | Example records |
|----------------|-------|-----------------|
| `United States` | 13 | US/Alaska, US/Arizona, US/Central, US/East-Indiana, US/Eastern, US/Hawaii, US/Indiana-Starke, US/Michigan, US/Mountain, US/Pacific, US/Pacific-New, US/Samoa, US/Aleutian |
| `Europe` | 63 | Europe/London, Europe/Paris, Europe/Prague, Europe/Rome, ... (all Europe/* zones) |
All other timezone records already have `group = name` (e.g., `Canada/Eastern` has
`group = "Canada/Eastern"`). The US and Europe records were loaded incorrectly.
**Effect:** `PARTITION BY group` collapsed all 13 US/* records into a single winner and
all 63 Europe/* records into a single winner. Only ~7 distinct US timezones and 1 Europe
timezone appeared in the dropdown instead of all 76.
### 2.2 Attempted fix broke country lookup deduplication
Changing `PARTITION BY group``PARTITION BY name` in `get_lookup_list_v3()` fixed the
timezone collapse but broke `lu_v3_country`.
`lu_v3_country` has (at minimum) two records for `alpha_2_code = "US"`:
- `id=240`: global default (`account_id=NULL`), `group="US"`
- `id=251`: account-specific (`account_id=1`), `group="US"`
With `PARTITION BY group`, both records share `group="US"` and are correctly deduped —
the account-specific record wins per the override hierarchy. With `PARTITION BY name`,
if the two records have different `name` values they are treated as separate identities
and both survive, resulting in duplicate `alpha_2_code="US"` entries in the API response.
The frontend's `{#each lu_country_list as country (country.alpha_2_code)}` then throws:
> `Svelte error: each_key_duplicate — Keyed each block has duplicate key 'US'`
The same risk applies to `lu_v3_country_subdivision`.
---
## 3. Correct Fix (Two Steps)
### Step 1 — Revert `app/methods/lookup_methods.py`
Change `PARTITION BY name` back to `PARTITION BY group`:
```python
# lookup_methods.py — get_lookup_list_v3()
ROW_NUMBER() OVER (
PARTITION BY `group` # <-- revert to this
ORDER BY
(for_type = :for_type AND for_id = :for_id) DESC,
(account_id = :account_id) DESC,
created_on DESC
) as rank_priority
```
This restores correct behavior for all three active V3 lookup types
(`country`, `country_subdivision`, `time_zone`).
### Step 2 — Fix the `lu_v3_time_zone` data
Set `group = name` for all records where the group is a regional label rather than the
timezone's own name. Run once against the database:
```sql
UPDATE lu_v3_time_zone
SET `group` = `name`
WHERE `group` IN ('United States', 'Europe');
```
**Verification:**
```sql
-- Should return 0 rows after the fix
SELECT `group`, COUNT(*) as cnt
FROM lu_v3_time_zone
GROUP BY `group`
HAVING cnt > 1;
```
---
## 4. Why PARTITION BY `group` Is Correct
As documented in `PROJECT__V3_UNIFORM_LOOKUP_SYSTEM.md` (Section 2.1):
> `group`: The primary business key/cluster key. *Note: Must be populated for hierarchy to work.*
The `group` field IS the deduplication identity. Each lookup type uses a different natural
key for `group`:
| Lookup type | `group` field | Example |
|---|---|---|
| `country` | `alpha_2_code` | `"US"`, `"CA"`, `"GB"` |
| `country_subdivision` | `code` | `"US-NY"`, `"CA-ON"` |
| `time_zone` | `name` (= the IANA timezone identifier) | `"US/Eastern"`, `"Europe/London"` |
For `time_zone`, `group` and `name` are intended to be the same value — each timezone
is its own identity. There is no meaningful concept of "override all US timezones as a
group." Each one is individually addressable.
---
## 5. Regression Tests to Add / Update
- `test_timezone_us_dedup()` — assert all 13 US/* priority zones are present individually
- `test_timezone_europe_dedup()` — assert all Europe/* priority zones present individually
- `test_country_us_dedup()` — assert only one `alpha_2_code="US"` record returned;
account-specific override wins over global default
- General: `GET /v3/lookup/time_zone/list?only_priority=true` should return exactly 72
records (the current count of priority=1 enabled timezones)
---
## 6. What Was NOT Changed (and Should Not Be)
- The endpoint signature for `GET /v3/lookup/{lu_type}/list` — it does not and should
not expose `limit`, `offset`, or `order_by_li` query params. The frontend sends these
but they are correctly ignored. The sort order is hardcoded and correct:
`ORDER BY COALESCE(priority, 0) DESC, COALESCE(sort, 0) DESC, name ASC`
- Country and country_subdivision data — no changes needed to those tables
- Frontend code — no backend-side changes are needed on the frontend for this fix