"""CSE Calc response mapper to the unified delivery schema.""" from decimal import Decimal, InvalidOperation from app.adapters.delivery_providers.cse.constants import ( CSE_PROVIDER_NAME, normalize_currency, ) from app.adapters.delivery_providers.cse.errors import CSEMappingError from app.adapters.delivery_providers.cse.soap import Element from app.schemas.response import DeliveryPrice _TARIFF_KEY = "Tariff" def map_cse_calc_response(root: Element) -> list[DeliveryPrice]: """Map a parsed ``Calc`` ``return`` Element into unified delivery prices.""" prices: list[DeliveryPrice] = [] for tariff in _iter_tariffs(root): price = _map_tariff(tariff) if price is not None: prices.append(price) return prices def map_cse_calc_response_for_tariff_code( root: Element, *, tariff_code: str, ) -> DeliveryPrice | None: """Return the tariff matching the given GUID, or ``None`` when absent.""" for tariff in _iter_tariffs(root): if tariff.value == tariff_code: return _map_tariff(tariff) return None def _iter_tariffs(root: Element): for destination in root.items: for tariff in destination.items: if tariff.key == _TARIFF_KEY: yield tariff def _map_tariff(tariff: Element) -> DeliveryPrice | None: tariff_code = tariff.value if not tariff_code: return None raw_total = tariff.field_value("Total") if raw_total is None: raise CSEMappingError("CSE tariff is missing Total.") try: price = Decimal(raw_total) except (InvalidOperation, TypeError, ValueError) as exc: raise CSEMappingError("CSE tariff Total is not a valid decimal.") from exc if not price.is_finite() or price <= 0: return None service_name = tariff.field_value("Service") or tariff.field_value("UrgencyName") if not service_name: service_name = tariff_code currency = normalize_currency(tariff.field_value("CurrencyName")) min_days = _to_int(tariff.field_value("MinPeriod")) max_days = _to_int(tariff.field_value("MaxPeriod")) if min_days is None: min_days = 0 if max_days is None or max_days < min_days: max_days = min_days try: return DeliveryPrice( provider=CSE_PROVIDER_NAME, service_name=str(service_name), price=price, currency=currency, delivery_days_min=min_days, delivery_days_max=max_days, tariff_code=tariff_code, bypass_parcel_type_filter=True, ) except (ArithmeticError, TypeError, ValueError) as exc: raise CSEMappingError("CSE tariff fields have invalid values.") from exc def _to_int(value: str | None) -> int | None: if value is None or value == "": return None try: return int(Decimal(value)) except (InvalidOperation, TypeError, ValueError): return None