This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
"""CSE Calc and SaveDocuments payload mappers."""
|
||||
"""CSE Calc, SaveDocuments and waybill payload mappers."""
|
||||
|
||||
import base64
|
||||
import binascii
|
||||
from dataclasses import dataclass
|
||||
|
||||
from app.adapters.delivery_providers.cse.constants import (
|
||||
@@ -32,6 +34,13 @@ class CSEOrderRegistrationResult:
|
||||
order_number: str
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class CSEOrderInfo:
|
||||
order_number: str
|
||||
status_code: str | None
|
||||
waybill_number: str | None
|
||||
|
||||
|
||||
def build_calc_body_for_calculation(
|
||||
request: DeliveryCalculationRequest,
|
||||
delivery_type: str = "",
|
||||
@@ -176,6 +185,73 @@ def map_cse_save_order_response(root: Element) -> CSEOrderRegistrationResult:
|
||||
raise CSEMappingError("CSE SaveDocuments response is missing document Number.")
|
||||
|
||||
|
||||
def build_tracking_body_for_order(order_number: str) -> dict[str, Element]:
|
||||
return {
|
||||
"documents": Element(
|
||||
key="Documents",
|
||||
items=[Element(key=order_number)],
|
||||
),
|
||||
"parameters": Element(
|
||||
key="parameters",
|
||||
items=[
|
||||
make_field("DocumentType", "Order"),
|
||||
make_field("OnlySelectedType", True, "boolean"),
|
||||
],
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def map_cse_tracking_response(root: Element) -> CSEOrderInfo:
|
||||
for document in root.items:
|
||||
order_number = document.property_value("Number") or document.key
|
||||
if not order_number:
|
||||
continue
|
||||
return CSEOrderInfo(
|
||||
order_number=order_number,
|
||||
status_code=_latest_tracking_status(document),
|
||||
waybill_number=_extract_waybill_number(document),
|
||||
)
|
||||
raise CSEMappingError("CSE Tracking response is missing document data.")
|
||||
|
||||
|
||||
def build_waybill_print_form_body(waybill_number: str) -> dict[str, Element]:
|
||||
return {
|
||||
"documents": Element(
|
||||
key="Documents",
|
||||
items=[Element(key=waybill_number)],
|
||||
),
|
||||
"parameters": Element(
|
||||
key="parameters",
|
||||
items=[
|
||||
make_field("DocumentType", "waybill"),
|
||||
make_field("Type", "print"),
|
||||
make_field(
|
||||
"Name",
|
||||
"Универсальная печатная "
|
||||
"форма документа НАКЛАДНАЯ",
|
||||
),
|
||||
make_field("Format", "pdf"),
|
||||
make_field("OnlySelectedType", True, "boolean"),
|
||||
],
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
def map_cse_waybill_print_form_response(root: Element) -> bytes:
|
||||
for document in root.items:
|
||||
bdata = document.bdata
|
||||
if not bdata:
|
||||
continue
|
||||
try:
|
||||
normalized_bdata = "".join(bdata.split())
|
||||
return base64.b64decode(normalized_bdata, validate=True)
|
||||
except (binascii.Error, ValueError) as exc:
|
||||
raise CSEMappingError(
|
||||
"CSE GetFormsForDocuments response contains invalid BData."
|
||||
) from exc
|
||||
raise CSEMappingError("CSE GetFormsForDocuments response is missing BData.")
|
||||
|
||||
|
||||
def _parcel_type(request: DeliveryCalculationRequest) -> str | None:
|
||||
return request.parcel_type.value if request.parcel_type is not None else None
|
||||
|
||||
@@ -190,3 +266,30 @@ def _compose_address(address: Address) -> str:
|
||||
|
||||
def _format_decimal(value: float) -> str:
|
||||
return format(value, "g")
|
||||
|
||||
|
||||
def _latest_tracking_status(document: Element) -> str | None:
|
||||
dated: list[tuple[str, str]] = []
|
||||
for state in document.items:
|
||||
if not state.key:
|
||||
continue
|
||||
date_time = state.property_value("DateTime") or ""
|
||||
dated.append((date_time, state.key))
|
||||
if not dated:
|
||||
return None
|
||||
dated.sort(key=lambda item: item[0])
|
||||
return dated[-1][1]
|
||||
|
||||
|
||||
def _extract_waybill_number(document: Element) -> str | None:
|
||||
for table in document.tables:
|
||||
if table.key != "Waybills":
|
||||
continue
|
||||
for waybill in table.items:
|
||||
document_type = waybill.property_value("DocumentType")
|
||||
if document_type is not None and document_type.lower() != "waybill":
|
||||
continue
|
||||
number = waybill.property_value("Number") or waybill.key
|
||||
if number:
|
||||
return number
|
||||
return None
|
||||
|
||||
Reference in New Issue
Block a user