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])