"""CDEK order registration payload mappers.""" from typing import Any from app.schemas.payment import ( InitPaymentRequest, PaymentPackage, PaymentParty, ) class CDEKOrderMappingError(ValueError): """Raised when CDEK order payload cannot be mapped.""" def map_cdek_order_request(request: InitPaymentRequest) -> dict[str, Any]: payload: dict[str, Any] = { "number": request.order_uuid, "type": request.type, "tariff_code": request.tariff_code, "sender": _map_order_party(request.sender), "recipient": _map_order_party(request.recipient), "from_location": request.from_location.model_dump(mode="python"), "to_location": request.to_location.model_dump(mode="python"), "packages": [_map_order_package(package) for package in request.packages], } if request.comment is not None: payload["comment"] = request.comment if request.services is not None: payload["services"] = [ service.model_dump(mode="python") for service in request.services ] return payload def map_cdek_order_response(payload: dict[str, Any]) -> str: entity = payload.get("entity") if not isinstance(entity, dict): raise CDEKOrderMappingError("CDEK order response must include entity object.") order_uuid = entity.get("uuid") if not isinstance(order_uuid, str) or not order_uuid: raise CDEKOrderMappingError("CDEK order response must include entity.uuid.") return order_uuid _CDEK_DUPLICATE_ORDER_ERROR_CODES = frozenset({"v2_entity_already_exists"}) def map_cdek_existing_order_response(payload: object) -> str | None: if not isinstance(payload, dict): return None if not _contains_cdek_duplicate_error_code(payload): return None try: return map_cdek_order_response(payload) except CDEKOrderMappingError: return _find_first_uuid(payload) def _map_order_party(party: PaymentParty) -> dict[str, Any]: return { "name": party.name, "email": party.email, "phones": [party.phone.model_dump(mode="python")], } def _map_order_package(package: PaymentPackage) -> dict[str, Any]: payload = package.model_dump(mode="python", exclude_none=True) payload["weight"] = package.weight * 1000 return payload def _contains_cdek_duplicate_error_code(payload: object) -> bool: if isinstance(payload, dict): code = payload.get("code") if isinstance(code, str) and code in _CDEK_DUPLICATE_ORDER_ERROR_CODES: return True return any( _contains_cdek_duplicate_error_code(value) for value in payload.values() ) if isinstance(payload, list): return any(_contains_cdek_duplicate_error_code(item) for item in payload) return False def _find_first_uuid(payload: object) -> str | None: if isinstance(payload, dict): value = payload.get("uuid") if isinstance(value, str) and value: return value for nested_value in payload.values(): nested_uuid = _find_first_uuid(nested_value) if nested_uuid is not None: return nested_uuid if isinstance(payload, list): for item in payload: nested_uuid = _find_first_uuid(item) if nested_uuid is not None: return nested_uuid return None