"""Exact lookups: Komm-Nr, DVN, VIN. Loco-Soft Komm-Nr-Schema: Type-Buchstabe (N/T/V/D/G/L) + DVN-Zahl (4-6 Stellen) Beispiele: 'D9094' (Nissan Leaf), 'N8093' (Askoll XKP45), 'L9083' (Opel) N = Neu, T = Tageszul., V = Vorfuehr, D = Differenzbest., G = Gebraucht, L = Leihgabe DVN allein ist eindeutig pro Fahrzeug, deshalb auch als Such-Einstieg möglich. """ import re from app import db from app.schemas import SearchResultItem COLUMNS = """ vehicle_id, dvn, commission_number, vin, brand, model, title, price::float8 as price, primary_image_id::text as primary_image_id, directus_product_id, dealer_vehicle_type """ KOMM_NR_RE = re.compile(r"^([NTVDGLntvdgl])\s*(\d{4,6})$") def normalize_komm_nr(raw: str) -> str | None: """'D 9094' / 'd9094' / ' D9094 ' -> 'D9094'. Returns None if not a valid pattern.""" if not raw: return None m = KOMM_NR_RE.match(raw.strip()) if not m: return None return m.group(1).upper() + m.group(2) async def by_komm_nr(raw: str) -> list[SearchResultItem]: """Lookup by full Komm-Nr (Type-Letter + DVN). Eindeutig wenn vorhanden.""" normalized = normalize_komm_nr(raw) if not normalized: return [] sql = f"SELECT {COLUMNS} FROM search_vehicles WHERE commission_number = $1 LIMIT 5" rows = await db.fetch(sql, normalized) return [_row_to_item(r, matched_via="exact_komm") for r in rows] async def by_dvn(number: str) -> list[SearchResultItem]: """Lookup by DVN allein (4-6 stellige Zahl ohne Type-Buchstabe). DVN ist eindeutig pro Fahrzeug, also liefert das immer 0 oder 1 Treffer.""" try: dvn_int = int(number) except (ValueError, TypeError): return [] sql = f"SELECT {COLUMNS} FROM search_vehicles WHERE dvn = $1 LIMIT 5" rows = await db.fetch(sql, dvn_int) return [_row_to_item(r, matched_via="exact_dvn") for r in rows] async def by_vin(vin: str) -> list[SearchResultItem]: sql = f"SELECT {COLUMNS} FROM search_vehicles WHERE vin = $1 LIMIT 5" rows = await db.fetch(sql, vin) return [_row_to_item(r, matched_via="exact_vin") for r in rows] def _row_to_item(row, matched_via: str) -> SearchResultItem: return SearchResultItem( vehicle_id=row["vehicle_id"], commission_number=row["commission_number"], vin=row["vin"], brand=row["brand"], model=row["model"], title=row["title"] or "", price=row["price"], primary_image_id=row["primary_image_id"], directus_product_id=row["directus_product_id"], score=1.0, matched_via=matched_via, )