first commit
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
import hashlib
|
||||
import re
|
||||
from flask import current_app
|
||||
from .http import get_json
|
||||
|
||||
LEGAL_SUFFIXES = re.compile(r"\b(SPÓŁKA|SPÓŁKA AKCYJNA|SP\. ?Z ?O\. ?O\.|S\. ?A\.|ODDZIAŁ|SPÓŁKA EUROPEJSKA)\b.*$", re.I)
|
||||
|
||||
|
||||
def fetch_ure_stations():
|
||||
payload = get_json(current_app.config["URE_STATIONS_URL"], timeout_key="URE_TIMEOUT_SECONDS")
|
||||
if isinstance(payload, list):
|
||||
return payload
|
||||
if isinstance(payload, dict):
|
||||
for key in ("items", "results", "data", "value"):
|
||||
if isinstance(payload.get(key), list):
|
||||
return payload[key]
|
||||
raise ValueError("Nieprawidłowa odpowiedź API URE")
|
||||
|
||||
|
||||
def _clean(value):
|
||||
return " ".join(str(value or "").strip().split())
|
||||
|
||||
|
||||
def infer_brand(company_name, station_name=""):
|
||||
combined = f"{_clean(company_name)} {_clean(station_name)}".upper()
|
||||
aliases = current_app.config.get("STATION_BRAND_ALIASES", {})
|
||||
# Najpierw szukamy marki w nazwie konkretnej stacji, później w przedsiębiorcy.
|
||||
for token, label in sorted(aliases.items(), key=lambda item: len(item[0]), reverse=True):
|
||||
if token.upper() in combined:
|
||||
return label
|
||||
normalized = _clean(company_name)
|
||||
shortened = LEGAL_SUFFIXES.sub("", normalized).strip(" ,-\"")
|
||||
return shortened or normalized or "Nieznana sieć"
|
||||
|
||||
|
||||
def _address_parts(row):
|
||||
return [
|
||||
_clean(row.get("infraUlica")),
|
||||
_clean(row.get("infraNrLokalu")),
|
||||
_clean(row.get("infraKod")) or _clean(row.get("kod")),
|
||||
_clean(row.get("infraPoczta")) or _clean(row.get("miejscowosc")) or _clean(row.get("poczta")),
|
||||
_clean(row.get("wojewodztwo")).lower(),
|
||||
]
|
||||
|
||||
|
||||
def _point_key(row, index):
|
||||
address = "|".join(x.casefold() for x in _address_parts(row) if x)
|
||||
station_name = _clean(row.get("nazwaStacji")).casefold()
|
||||
raw = address or f"{station_name}|{index}"
|
||||
digest = hashlib.sha1(raw.encode("utf-8")).hexdigest()[:16]
|
||||
dkn = _clean(row.get("dkn"))
|
||||
storage_key = f"{dkn or 'no-dkn'}:{digest}"
|
||||
return raw, storage_key
|
||||
|
||||
|
||||
def _merge_point(target, source):
|
||||
for field in ("station_name", "street", "street_number", "postal_code", "city", "region", "coordinates"):
|
||||
if not target.get(field) and source.get(field):
|
||||
target[field] = source[field]
|
||||
for field in ("has_petrol", "has_diesel", "has_lpg"):
|
||||
target[field] = bool(target.get(field) or source.get(field))
|
||||
|
||||
|
||||
def aggregate_ure_companies(rows):
|
||||
grouped = {}
|
||||
aliases = {label.casefold() for label in current_app.config.get("STATION_BRAND_ALIASES", {}).values()}
|
||||
for index, row in enumerate(rows, start=1):
|
||||
nip, regon = _clean(row.get("nip")), _clean(row.get("regon"))
|
||||
company_name = _clean(row.get("nazwa")) or "Nieznana firma"
|
||||
station_name = _clean(row.get("nazwaStacji"))
|
||||
brand = infer_brand(company_name, station_name)
|
||||
# Rozpoznane sieci agregujemy jako jedną markę, niezależnie od operatora/franczyzobiorcy.
|
||||
if brand.casefold() in aliases:
|
||||
key = f"brand:{brand.casefold()}"
|
||||
else:
|
||||
key = f"nip:{nip}" if nip else (f"regon:{regon}" if regon else f"name:{company_name.casefold()}")
|
||||
item = grouped.setdefault(key, {
|
||||
"ure_key": key,
|
||||
"brand_name": brand,
|
||||
"company_name": brand if key.startswith("brand:") else company_name,
|
||||
"nip": None if key.startswith("brand:") else (nip or None),
|
||||
"regon": None if key.startswith("brand:") else (regon or None),
|
||||
"station_names": set(), "regions": set(),
|
||||
"has_petrol": False, "has_diesel": False, "has_lpg": False,
|
||||
"points": {},
|
||||
})
|
||||
if station_name: item["station_names"].add(station_name)
|
||||
region = _clean(row.get("wojewodztwo")).lower()
|
||||
if region: item["regions"].add(region)
|
||||
item["has_petrol"] |= bool(row.get("benzynySilnikowe"))
|
||||
item["has_diesel"] |= bool(row.get("olejeNapedowe"))
|
||||
item["has_lpg"] |= bool(row.get("gazPlynnyLPG"))
|
||||
point_key, stored_dkn = _point_key(row, index)
|
||||
point = {
|
||||
"ure_dkn": stored_dkn,
|
||||
"station_name": station_name or brand,
|
||||
"street": _clean(row.get("infraUlica")), "street_number": _clean(row.get("infraNrLokalu")),
|
||||
"postal_code": _clean(row.get("infraKod")) or _clean(row.get("kod")),
|
||||
"city": _clean(row.get("infraPoczta")) or _clean(row.get("miejscowosc")) or _clean(row.get("poczta")),
|
||||
"region": region, "coordinates": _clean(row.get("wspolrzedne")),
|
||||
"has_petrol": bool(row.get("benzynySilnikowe")), "has_diesel": bool(row.get("olejeNapedowe")), "has_lpg": bool(row.get("gazPlynnyLPG")),
|
||||
}
|
||||
existing = item["points"].get(point_key)
|
||||
_merge_point(existing, point) if existing else item["points"].__setitem__(point_key, point)
|
||||
result = []
|
||||
for item in grouped.values():
|
||||
item["points"] = list(item["points"].values())
|
||||
item["station_count"] = len(item["points"])
|
||||
item["station_names"] = "|".join(sorted(item["station_names"], key=str.casefold))
|
||||
item["regions"] = "|".join(sorted(item["regions"], key=str.casefold))
|
||||
result.append(item)
|
||||
return sorted(result, key=lambda x: (x["brand_name"].casefold(), x["company_name"].casefold()))
|
||||
Reference in New Issue
Block a user