diff --git a/app/adapters/delivery_providers/cse/client.py b/app/adapters/delivery_providers/cse/client.py index 51a3f15..ad5a95c 100644 --- a/app/adapters/delivery_providers/cse/client.py +++ b/app/adapters/delivery_providers/cse/client.py @@ -214,17 +214,16 @@ class CSEClient: operation: str, request_error_message: str, ) -> None: - for prop in root.properties: - if prop.key == "Error": - codes = [item.value for item in prop.items if item.value] - log.warning( - "cse_response_error", - operation=operation, - error_codes=codes, - ) - raise CSERequestError( - f"{request_error_message} application error {codes}." - ) + error_codes = _response_error_codes(root) + if error_codes: + log.warning( + "cse_response_error", + operation=operation, + error_codes=error_codes, + ) + raise CSERequestError( + f"{request_error_message} application error {error_codes}." + ) @staticmethod def _should_retry(status_code: int) -> bool: @@ -238,6 +237,20 @@ def _response_excerpt(text: str, *, limit: int = 1000) -> str: return " ".join(text.split())[:limit] +def _response_error_codes(root: Element) -> list[str]: + codes: list[str] = [] + _collect_response_error_codes(root, codes) + return codes + + +def _collect_response_error_codes(element: Element, codes: list[str]) -> None: + for prop in element.properties: + if prop.key == "Error": + codes.extend(item.value for item in prop.items if item.value) + for child in (*element.items, *element.tables): + _collect_response_error_codes(child, codes) + + class CSEProvider(DeliveryProvider): name = CSE_PROVIDER_NAME diff --git a/tests/adapters/delivery_providers/cse/test_cse_adapter.py b/tests/adapters/delivery_providers/cse/test_cse_adapter.py index 8389512..a20a709 100644 --- a/tests/adapters/delivery_providers/cse/test_cse_adapter.py +++ b/tests/adapters/delivery_providers/cse/test_cse_adapter.py @@ -71,6 +71,29 @@ _SAVE_RESPONSE = """ """ +_SAVE_RESPONSE_DOCUMENT_ERROR = """ + + + + + SaveDocuments + + Order + + Error + true + boolean + + Description + SenderAddress is invalid + + + + + + +""" + _TRACKING_RESPONSE = """ @@ -541,6 +564,38 @@ def test_provider_register_order_returns_document_number() -> None: assert http_client.calls[0]["url"] == "http://lk-test.cse.ru/1c/ws/web1c.1cws" +def test_provider_register_order_raises_document_level_error() -> None: + response = httpx.Response(200, text=_SAVE_RESPONSE_DOCUMENT_ERROR) + client, _ = _build_client([response]) + provider = CSEProvider(client) + + with pytest.raises(CSERequestError, match="SenderAddress is invalid"): + asyncio.run( + provider.register_order( + make_init_payment_request( + systemData={ + "tariff": { + "provider": "cse", + "serviceName": "Экспресс", + "price": 200000, + "deliveryDaysMin": 1, + "deliveryDaysMax": 2, + "tariffCode": "ДоставкаДоДверей|tariff-guid-2|urg-exp", + }, + "parcelType": "parcel", + "weight": "1.0", + "dimensions": { + "length": "10", + "width": "10", + "height": "10", + }, + } + ), + "order-uuid-1", + ) + ) + + def test_provider_get_order_extracts_waybill_number_from_tracking() -> None: response = httpx.Response(200, text=_TRACKING_RESPONSE) client, http_client = _build_client([response])