mirror of
https://github.com/Hestia-Homes/Model.git
synced 2026-07-12 13:29:04 +00:00
Runner-up number fills the contact's secondary phone number 🟩
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
10636c1752
commit
52f2286ee9
2 changed files with 45 additions and 7 deletions
|
|
@ -1,4 +1,5 @@
|
|||
import xml.etree.ElementTree as ET
|
||||
from dataclasses import dataclass
|
||||
from datetime import date
|
||||
from typing import List, Optional, Tuple, Union
|
||||
|
||||
|
|
@ -38,10 +39,45 @@ def _phone_priority(entry: ET.Element) -> Tuple[int, int]:
|
|||
return (1, 0)
|
||||
|
||||
|
||||
def _select_phone_number(entries: List[ET.Element]) -> Optional[str]:
|
||||
usable = [entry for entry in entries if (entry.text or "").strip()]
|
||||
ranked = sorted(usable, key=_phone_priority) # stable: ties keep document order
|
||||
return (ranked[0].text or "").strip() if ranked else None
|
||||
def _best_phone_number(entries: List[ET.Element]) -> Optional[ET.Element]:
|
||||
ranked = sorted(entries, key=_phone_priority) # stable: ties keep document order
|
||||
return ranked[0] if ranked else None
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class _SelectedPhoneNumbers:
|
||||
mobile: Optional[str]
|
||||
telephone: Optional[str]
|
||||
secondary: Optional[str]
|
||||
|
||||
|
||||
def _select_phone_numbers(tenant_element: ET.Element) -> _SelectedPhoneNumbers:
|
||||
"""Best mobile, best landline, then the best of the leftovers of both kinds.
|
||||
|
||||
All three picks use the same rule: lowest numeric priority wins, entries
|
||||
without a usable priority sort last, ties break by document order, blank
|
||||
numbers are ignored.
|
||||
"""
|
||||
usable = [
|
||||
entry
|
||||
for entry in tenant_element
|
||||
if entry.tag in ("Mobile", "Telephone") and (entry.text or "").strip()
|
||||
]
|
||||
|
||||
best_mobile = _best_phone_number([e for e in usable if e.tag == "Mobile"])
|
||||
best_telephone = _best_phone_number([e for e in usable if e.tag == "Telephone"])
|
||||
runner_up = _best_phone_number(
|
||||
[e for e in usable if e is not best_mobile and e is not best_telephone]
|
||||
)
|
||||
|
||||
def _text(entry: Optional[ET.Element]) -> Optional[str]:
|
||||
return (entry.text or "").strip() if entry is not None else None
|
||||
|
||||
return _SelectedPhoneNumbers(
|
||||
mobile=_text(best_mobile),
|
||||
telephone=_text(best_telephone),
|
||||
secondary=_text(runner_up),
|
||||
)
|
||||
|
||||
|
||||
class AbriClient:
|
||||
|
|
@ -211,12 +247,13 @@ class AbriClient:
|
|||
def _parse_tenant(element: ET.Element) -> Tenant:
|
||||
# Data minimisation: person_title, main-contact and the per-person
|
||||
# reference (the element text) are deliberately not read.
|
||||
numbers = _select_phone_numbers(element)
|
||||
return Tenant(
|
||||
forenames=(element.get("forenames") or "").strip(),
|
||||
surname=(element.get("surname") or "").strip(),
|
||||
mobile=_select_phone_number(element.findall("Mobile")),
|
||||
telephone=_select_phone_number(element.findall("Telephone")),
|
||||
secondary_number=None,
|
||||
mobile=numbers.mobile,
|
||||
telephone=numbers.telephone,
|
||||
secondary_number=numbers.secondary,
|
||||
vulnerabilities=(),
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ def _contact_properties(tenant: Tenant) -> Dict[str, str]:
|
|||
"lastname": tenant.surname,
|
||||
"mobilephone": tenant.mobile,
|
||||
"phone": tenant.telephone,
|
||||
"secondary_phone_number": tenant.secondary_number,
|
||||
}
|
||||
properties = {name: value for name, value in candidates.items() if value}
|
||||
# Always written, so "not vulnerable" is distinguishable from "not synced".
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue