Model/backend/utils/epc_address_match.py
Khalim Conn-Kowlessar a1b207ba55 bolstering testing
2026-04-28 13:46:09 +00:00

67 lines
1.8 KiB
Python

from __future__ import annotations
from typing import TYPE_CHECKING, Optional
from backend.utils.addressMatch import AddressMatch
from datatypes.epc.domain.epc_property_data import EpcPropertyData
from datatypes.epc.search import EpcSearchResult
if TYPE_CHECKING:
from backend.epc_client.client import EpcClientService
_MIN_MATCH_SCORE = 0.6
def find_best_epc_match(
service: EpcClientService,
postcode: str,
address: str,
) -> Optional[EpcPropertyData]:
candidates = service.search_by_postcode(postcode)
if not candidates:
return None
cert_num = _pick_best_cert(candidates, address, use_full_address=False)
if cert_num:
return _safe_get(service, cert_num)
cert_num = _pick_best_cert(candidates, address, use_full_address=True)
if cert_num:
return _safe_get(service, cert_num)
return None
def _pick_best_cert(
candidates: list[EpcSearchResult],
user_address: str,
use_full_address: bool,
) -> Optional[str]:
scored: list[tuple[float, str]] = [
(
AddressMatch.score(
user_address,
r.full_address if use_full_address else r.address_line_1,
),
r.certificate_number,
)
for r in candidates
]
if not scored:
return None
best_score = max(s for s, _ in scored)
if best_score < _MIN_MATCH_SCORE:
return None
top = [cert for s, cert in scored if s == best_score]
if len(top) != 1:
return None
return top[0]
def _safe_get(service: EpcClientService, cert_num: str) -> Optional[EpcPropertyData]:
from backend.epc_client.exceptions import EpcNotFoundError
try:
return service.get_by_certificate_number(cert_num)
except EpcNotFoundError:
return None