Добавлен поллер накладной

This commit is contained in:
Раис Юсупалиев
2026-05-23 20:24:23 +03:00
parent c494d50566
commit 5526f90cb3
23 changed files with 1481 additions and 61 deletions
+221 -31
View File
@@ -1,5 +1,6 @@
import asyncio
from collections.abc import Awaitable, Callable
from datetime import datetime, timezone
from typing import Any
import pytest
@@ -173,7 +174,7 @@ def test_mark_payment_status_returns_none_for_missing_order() -> None:
asyncio.run(_with_repository(run))
def test_mark_cdek_order_registered_persists_cdek_order_and_waybill() -> None:
def test_mark_cdek_order_registered_persists_cdek_order_uuid_only() -> None:
async def run(
repository: OrderRepository,
session_factory: async_sessionmaker[AsyncSession],
@@ -186,8 +187,6 @@ def test_mark_cdek_order_registered_persists_cdek_order_and_waybill() -> None:
session,
"order-uuid-1",
"cdek-order-uuid-1",
"waybill-uuid-1",
"https://cdek.test/waybill/1.pdf",
)
async with session_factory() as session:
@@ -197,34 +196,6 @@ def test_mark_cdek_order_registered_persists_cdek_order_and_waybill() -> None:
persisted_order = result.scalar_one()
assert order is not None
assert persisted_order.cdek_order_uuid == "cdek-order-uuid-1"
assert persisted_order.cdek_waybill_uuid == "waybill-uuid-1"
assert persisted_order.cdek_waybill_url == "https://cdek.test/waybill/1.pdf"
asyncio.run(_with_repository(run))
def test_mark_cdek_order_registered_allows_missing_waybill_fields() -> None:
async def run(
repository: OrderRepository,
session_factory: async_sessionmaker[AsyncSession],
) -> None:
async with repository.session() as session:
await repository.create_order(session, _make_order_data())
async with repository.session() as session:
await repository.mark_cdek_order_registered(
session,
"order-uuid-1",
"cdek-order-uuid-1",
)
async with session_factory() as session:
result = await session.execute(
select(Order).where(Order.order_uuid == "order-uuid-1")
)
persisted_order = result.scalar_one()
assert persisted_order.cdek_order_uuid == "cdek-order-uuid-1"
assert persisted_order.cdek_waybill_uuid is None
assert persisted_order.cdek_waybill_url is None
@@ -279,3 +250,222 @@ def test_mark_cdek_order_registered_returns_none_for_missing_order() -> None:
assert order is None
asyncio.run(_with_repository(run))
async def _seed_order(
repository: OrderRepository,
*,
order_uuid: str,
cdek_order_uuid: str | None,
cdek_order_status: str | None = None,
cdek_waybill_uuid: str | None = None,
cdek_waybill_url: str | None = None,
cdek_polled_at: datetime | None = None,
) -> None:
async with repository.session() as session:
await repository.create_order(
session, _make_order_data(order_uuid=order_uuid)
)
if cdek_order_uuid is not None:
await repository.mark_cdek_order_registered(
session, order_uuid, cdek_order_uuid
)
if (
cdek_order_status is not None
or cdek_waybill_uuid is not None
or cdek_polled_at is not None
):
order = await repository.get_order_by_order_uuid(session, order_uuid)
assert order is not None
if cdek_order_status is not None:
order.cdek_order_status = cdek_order_status
if cdek_waybill_uuid is not None:
order.cdek_waybill_uuid = cdek_waybill_uuid
if cdek_polled_at is not None:
order.cdek_polled_at = cdek_polled_at
if cdek_waybill_url is not None:
order = await repository.get_order_by_order_uuid(session, order_uuid)
assert order is not None
order.cdek_waybill_url = cdek_waybill_url
def test_list_orders_pending_waybill_returns_orders_without_url() -> None:
async def run(
repository: OrderRepository,
_session_factory: async_sessionmaker[AsyncSession],
) -> None:
await _seed_order(repository, order_uuid="pending", cdek_order_uuid="o1")
await _seed_order(
repository,
order_uuid="done",
cdek_order_uuid="o2",
cdek_waybill_uuid="w2",
cdek_waybill_url="https://cdek.test/2.pdf",
)
await _seed_order(
repository,
order_uuid="invalid",
cdek_order_uuid="o3",
cdek_order_status="INVALID",
)
await _seed_order(repository, order_uuid="no-cdek", cdek_order_uuid=None)
async with repository.session() as session:
orders = await repository.list_orders_pending_waybill(session, limit=10)
assert [order.order_uuid for order in orders] == ["pending"]
asyncio.run(_with_repository(run))
def test_list_orders_pending_waybill_orders_polled_at_nulls_first() -> None:
earlier = datetime(2026, 5, 24, 10, 0, tzinfo=timezone.utc)
later = datetime(2026, 5, 24, 11, 0, tzinfo=timezone.utc)
async def run(
repository: OrderRepository,
_session_factory: async_sessionmaker[AsyncSession],
) -> None:
await _seed_order(
repository,
order_uuid="late",
cdek_order_uuid="o-late",
cdek_polled_at=later,
)
await _seed_order(
repository,
order_uuid="early",
cdek_order_uuid="o-early",
cdek_polled_at=earlier,
)
await _seed_order(repository, order_uuid="never", cdek_order_uuid="o-never")
async with repository.session() as session:
orders = await repository.list_orders_pending_waybill(session, limit=10)
assert [order.order_uuid for order in orders] == ["never", "early", "late"]
asyncio.run(_with_repository(run))
def test_record_order_poll_sets_status_and_waybill_uuid() -> None:
polled = datetime(2026, 5, 24, 12, 0, tzinfo=timezone.utc)
async def run(
repository: OrderRepository,
_session_factory: async_sessionmaker[AsyncSession],
) -> None:
await _seed_order(repository, order_uuid="o", cdek_order_uuid="cdek-o")
async with repository.session() as session:
order = await repository.record_order_poll(
session,
order_uuid="o",
order_status="ACCEPTED",
waybill_uuid="waybill-1",
polled_at=polled,
)
assert order is not None
assert order.cdek_order_status == "ACCEPTED"
assert order.cdek_waybill_uuid == "waybill-1"
assert order.cdek_polled_at == polled
asyncio.run(_with_repository(run))
def test_record_order_poll_does_not_overwrite_existing_waybill_uuid() -> None:
polled = datetime(2026, 5, 24, 12, 0, tzinfo=timezone.utc)
async def run(
repository: OrderRepository,
_session_factory: async_sessionmaker[AsyncSession],
) -> None:
await _seed_order(
repository,
order_uuid="o",
cdek_order_uuid="cdek-o",
cdek_waybill_uuid="existing-waybill",
)
async with repository.session() as session:
order = await repository.record_order_poll(
session,
order_uuid="o",
order_status="ACCEPTED",
waybill_uuid="new-waybill",
polled_at=polled,
)
assert order is not None
assert order.cdek_waybill_uuid == "existing-waybill"
asyncio.run(_with_repository(run))
def test_record_waybill_poll_sets_url_only_when_previously_null() -> None:
polled = datetime(2026, 5, 24, 13, 0, tzinfo=timezone.utc)
async def run(
repository: OrderRepository,
_session_factory: async_sessionmaker[AsyncSession],
) -> None:
await _seed_order(
repository,
order_uuid="o",
cdek_order_uuid="cdek-o",
cdek_waybill_uuid="waybill-1",
)
async with repository.session() as session:
order = await repository.record_waybill_poll(
session,
order_uuid="o",
waybill_url="https://cdek.test/1.pdf",
polled_at=polled,
)
assert order is not None
assert order.cdek_waybill_url == "https://cdek.test/1.pdf"
assert order.cdek_polled_at == polled
async with repository.session() as session:
order = await repository.record_waybill_poll(
session,
order_uuid="o",
waybill_url="https://cdek.test/REPLACED.pdf",
polled_at=polled,
)
assert order is not None
assert order.cdek_waybill_url == "https://cdek.test/1.pdf"
asyncio.run(_with_repository(run))
def test_record_waybill_poll_updates_polled_at_when_url_is_none() -> None:
polled = datetime(2026, 5, 24, 13, 0, tzinfo=timezone.utc)
async def run(
repository: OrderRepository,
_session_factory: async_sessionmaker[AsyncSession],
) -> None:
await _seed_order(
repository,
order_uuid="o",
cdek_order_uuid="cdek-o",
cdek_waybill_uuid="waybill-1",
)
async with repository.session() as session:
order = await repository.record_waybill_poll(
session,
order_uuid="o",
waybill_url=None,
polled_at=polled,
)
assert order is not None
assert order.cdek_waybill_url is None
assert order.cdek_polled_at == polled
asyncio.run(_with_repository(run))