добавлено получение накладной в cse
Deploy / deploy (push) Successful in 2m33s

This commit is contained in:
Раис Юсупалиев
2026-06-27 07:10:31 +03:00
parent 2d8f31d3d9
commit facdde00c9
14 changed files with 581 additions and 100 deletions
+41 -5
View File
@@ -10,6 +10,8 @@ from app.services.waybill_email_sender import WaybillEmailSenderService
class StoredOrder:
order_uuid: str
account_email: str
provider: str = "cdek"
provider_waybill_id: str | None = None
provider_waybill_url: str | None = None
waybill_email_sent_at: datetime | None = None
@@ -41,7 +43,10 @@ class StubRepository:
return [
order
for order in self._orders.values()
if order.provider_waybill_url is not None
if (
order.provider_waybill_url is not None
or order.provider_waybill_id is not None
)
and order.waybill_email_sent_at is None
]
@@ -68,9 +73,11 @@ class StubDownloader:
self._results = results
self.calls: list[str] = []
async def download_waybill_pdf(self, url: str) -> bytes:
self.calls.append(url)
result = self._results[url]
async def download_waybill_pdf(self, order: StoredOrder) -> bytes:
locator = order.provider_waybill_url or order.provider_waybill_id
assert locator is not None
self.calls.append(locator)
result = self._results[locator]
if isinstance(result, Exception):
raise result
return result
@@ -114,7 +121,7 @@ def _make_service(
) -> WaybillEmailSenderService:
return WaybillEmailSenderService(
order_repository=repository,
waybill_downloader=downloader or StubDownloader({}),
waybill_downloaders={"cdek": downloader or StubDownloader({})},
email_sender=email_sender or StubEmailSender(),
batch_size=10,
datetime_now=lambda: _SENT_AT,
@@ -151,6 +158,35 @@ def test_poll_once_downloads_pdf_sends_email_and_marks_sent() -> None:
assert order.waybill_email_sent_at == _SENT_AT
def test_poll_once_sends_cse_waybill_pdf_without_url() -> None:
order = StoredOrder(
order_uuid="o-1",
provider="cse",
account_email="client@example.com",
provider_waybill_id="496-AA-1676378",
)
repo = StubRepository([order])
downloader = StubDownloader({"496-AA-1676378": b"%PDF"})
email_sender = StubEmailSender()
service = WaybillEmailSenderService(
order_repository=repo,
waybill_downloaders={"cse": downloader},
email_sender=email_sender,
batch_size=10,
datetime_now=lambda: _SENT_AT,
)
summary = asyncio.run(service.poll_once())
assert summary.processed == 1
assert summary.succeeded == 1
assert downloader.calls == ["496-AA-1676378"]
assert len(email_sender.calls) == 1
assert "https://" not in email_sender.calls[0]["body"]
assert email_sender.calls[0]["attachment_bytes"] == b"%PDF"
assert order.waybill_email_sent_at == _SENT_AT
def test_poll_once_download_error_keeps_order_pending_and_skips_send() -> None:
order = StoredOrder(
order_uuid="o-1",
+40 -2
View File
@@ -7,12 +7,14 @@ from app.adapters.delivery_providers.cdek.order_mapper import (
CDEKOrderInfo,
CDEKWaybillInfo,
)
from app.adapters.delivery_providers.cse.order_mapper import CSEOrderInfo
from app.services.waybill_poller import WaybillPollerService
@dataclass
class StoredOrder:
order_uuid: str
provider: str = "cdek"
provider_order_id: str | None = None
provider_order_status: str | None = None
provider_waybill_id: str | None = None
@@ -129,6 +131,9 @@ class StubWaybillInfoAdapter:
_POLLED_AT = datetime(2026, 5, 24, 12, 0, tzinfo=timezone.utc)
_CSE_WAYBILL_CREATED_STATUS = (
"На основании заказа оформлена накладная."
)
def _make_service(
@@ -139,8 +144,8 @@ def _make_service(
) -> WaybillPollerService:
return WaybillPollerService(
order_repository=repository,
order_info_adapter=order_info or StubOrderInfoAdapter({}),
waybill_info_adapter=waybill_info or StubWaybillInfoAdapter({}),
order_info_adapters={"cdek": order_info or StubOrderInfoAdapter({})},
waybill_info_adapters={"cdek": waybill_info or StubWaybillInfoAdapter({})},
batch_size=10,
datetime_now=lambda: _POLLED_AT,
)
@@ -194,6 +199,39 @@ def test_poll_once_fetches_waybill_info_when_waybill_uuid_is_present() -> None:
assert order.provider_polled_at == _POLLED_AT
def test_poll_once_fetches_cse_waybill_number_from_order_tracking() -> None:
order = StoredOrder(
order_uuid="o",
provider="cse",
provider_order_id="CSE-000123",
)
repo = StubRepository([order])
order_info = StubOrderInfoAdapter(
{
"CSE-000123": CSEOrderInfo(
order_number="CSE-000123",
status_code=_CSE_WAYBILL_CREATED_STATUS,
waybill_number="496-AA-1676378",
)
}
)
service = WaybillPollerService(
order_repository=repo,
order_info_adapters={"cse": order_info},
waybill_info_adapters={},
batch_size=10,
datetime_now=lambda: _POLLED_AT,
)
summary = asyncio.run(service.poll_once())
assert summary.processed == 1 and summary.succeeded == 1 and summary.failed == 0
assert order_info.calls == ["CSE-000123"]
assert order.provider_order_status == _CSE_WAYBILL_CREATED_STATUS
assert order.provider_waybill_id == "496-AA-1676378"
assert order.provider_polled_at == _POLLED_AT
def test_poll_once_records_terminal_status_without_waybill() -> None:
order = StoredOrder(order_uuid="o", provider_order_id="cdek-o")
repo = StubRepository([order])