"""Karten finden, die dieselbe Person meinen. Auf Messen trifft man Leute wieder, und dieselbe Karte landet ein zweites Mal im Stapel. Verglichen wird nicht der ganze Datensatz, sondern das, was eine Person eindeutig macht - in dieser Reihenfolge, weil die Aussagekraft faellt. """ from . import db def _phone_key(value) -> str: """Nur die letzten acht Ziffern. Damit passen +49 511 123456, 0049511123456 und 0511/123456 aufeinander.""" digits = "".join(character for character in (value or "") if character.isdigit()) return digits[-8:] if len(digits) >= 8 else "" def _phone_keys(row) -> set: return {_phone_key(row["phone"]), _phone_key(row["mobile"])} - {""} def _clean(value) -> str: return (value or "").strip().lower() def _match(card, other) -> str: email = _clean(card["email"]) if email and _clean(other["email"]) == email: return "gleiche E-Mail" if _phone_keys(card) & _phone_keys(other): return "gleiche Telefonnummer" last_name, company = _clean(card["last_name"]), _clean(card["company"]) if last_name and company: if _clean(other["last_name"]) == last_name and _clean(other["company"]) == company: return "gleicher Name und dieselbe Firma" return "" def find(card) -> list: """Aehnliche Karten, neueste zuerst.""" others = db.query( """ SELECT id, full_name, first_name, last_name, company, email, phone, mobile, occasion, captured_at, created_at FROM cards WHERE id <> ? AND extract_status <> 'offen' ORDER BY COALESCE(captured_at, created_at) DESC """, (card["id"],), ) hits = [] for other in others: reason = _match(card, other) if reason: hits.append({**dict(other), "reason": reason}) return hits