Files
OSIT-AE-API-FastAPI/app/methods/lookup_methods.py
Scott Idem c9ec3d7ea1 revert(lookup): restore PARTITION BY group; tests now track data fix
Reverts the PARTITION BY name change — group is the correct dedup key.
Partitioning by name broke country deduplication (two US records both
survived, causing Svelte each_key_duplicate on alpha_2_code='US').

Root cause is bad seed data in lu_v3_time_zone: group='United States'
for 13 US/* zones and group='Europe' for 63 Europe/* zones instead of
group=name. A separate DB UPDATE is required to fix those rows.

Tests updated to assert:
- No duplicate alpha_2_code in country list (PARTITION BY group regression)
- All 13 US/* and Europe/* spot-check zones present (pending DB data fix)
- priority-only timezone count == 72 (pending DB data fix)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 17:31:30 -04:00

97 lines
2.9 KiB
Python

import logging
from typing import List, Optional
from sqlalchemy import text
from app.lib_sql_core import engine
from app.lib_general_v3 import AccountContext
log = logging.getLogger(__name__)
def get_lookup_list_v3(
lu_type: str,
account_ctx: AccountContext,
for_type: Optional[str] = None,
for_id: Optional[int] = None,
include_disabled: bool = False,
whitelist: Optional[List[str]] = None,
only_priority: bool = False
) -> List[dict]:
"""
Retrieves a ranked, deduplicated list of lookup records.
Priority: Object Override > Account Override > Global Default.
Supports an optional whitelist and priority filtering.
"""
table_name = f"v_lu_v3_{lu_type}"
# We use ROW_NUMBER() to handle the hierarchy
sql = f"""
SELECT * FROM (
SELECT *,
ROW_NUMBER() OVER (
PARTITION BY `group`
ORDER BY
(for_type = :for_type AND for_id = :for_id) DESC,
(account_id = :account_id) DESC,
created_on DESC
) as rank_priority
FROM `{table_name}`
WHERE ((for_type = :for_type AND for_id = :for_id)
OR account_id = :account_id
OR account_id IS NULL)
"""
if whitelist:
sql += " AND `group` IN :whitelist"
sql += f"""
) AS ranked
WHERE rank_priority = 1
"""
if not include_disabled:
sql += " AND enable = 1"
if only_priority:
sql += " AND priority = 1"
sql += " ORDER BY COALESCE(priority, 0) DESC, COALESCE(sort, 0) DESC, name ASC"
params = {
"account_id": account_ctx.account_id,
"for_type": for_type,
"for_id": for_id,
"whitelist": tuple(whitelist) if whitelist else None
}
try:
with engine.connect() as conn:
result = conn.execute(text(sql), params)
return [dict(row._mapping) for row in result]
except Exception as e:
log.error(f"Error in get_lookup_list_v3: {e}")
return []
def resolve_lookup_v3(
lu_type: str,
query: str,
account_ctx: AccountContext,
identity_fields: List[str]
) -> Optional[dict]:
"""
Resolves a query string to a single lookup record by scanning multiple identity fields.
Returns the highest-priority match.
"""
# Simple implementation: get the full ranked list and find first match in identity fields
# For performance with large tables (like timezones), we might want a specific SQL query
full_list = get_lookup_list_v3(lu_type, account_ctx)
query_clean = query.strip().lower()
for item in full_list:
for field in identity_fields:
val = item.get(field)
if val and str(val).lower() == query_clean:
return item
return None