Files
OSIT-AE-API-FastAPI/documentation/PROJECT__AE_Lookups_fixes_and_docs_update.md
2026-03-23 17:50:59 -04:00

5.6 KiB

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 groupPARTITION 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:

# 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:

UPDATE lu_v3_time_zone
SET `group` = `name`
WHERE `group` IN ('United States', 'Europe');

Verification:

-- 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