Add COD-in-transit summary and received tab to the dashboard
- GET /orders/summary: count and sum of cash-on-delivery for parcels not yet picked up (excludes received, refused, deleted/unknown TTNs, paid COD); shown as a card above the tabs. - New «Полученные» tab: orders with NP received codes (9, 10, 11, 106) move there automatically, regardless of receipt; 106 is now a final status. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -16,6 +16,7 @@ from app.services.orders import (
|
||||
OrderTab,
|
||||
_parse_crm_datetime,
|
||||
_to_kopecks,
|
||||
cod_in_transit,
|
||||
list_orders,
|
||||
update_order,
|
||||
)
|
||||
@@ -185,8 +186,48 @@ class TestListOrders:
|
||||
assert "orders.np_status_code IN ('102', '103', '105', '108')" in sql
|
||||
assert "receipt_created_at" not in sql
|
||||
|
||||
def test_received_tab_filters_by_received_codes_only(self) -> None:
|
||||
sql = _list_where(OrderTab.RECEIVED)
|
||||
assert "orders.np_status_code IN ('9', '10', '11', '106')" in sql
|
||||
assert "receipt_created_at" not in sql
|
||||
|
||||
@pytest.mark.parametrize("tab", [OrderTab.NO_RECEIPT, OrderTab.HAS_RECEIPT])
|
||||
def test_other_tabs_exclude_refusals(self, tab: OrderTab) -> None:
|
||||
def test_other_tabs_exclude_received_and_refusals(self, tab: OrderTab) -> None:
|
||||
sql = _list_where(tab)
|
||||
assert "NOT IN ('102', '103', '105', '108')" in sql
|
||||
assert "NOT IN ('9', '10', '11', '106', '102', '103', '105', '108')" in sql
|
||||
assert "receipt_created_at" in sql
|
||||
|
||||
|
||||
class _CapturingExecuteSession:
|
||||
def __init__(self) -> None:
|
||||
self.statement: Any = None
|
||||
|
||||
async def execute(self, statement: Any) -> Any:
|
||||
self.statement = statement
|
||||
|
||||
class _Result:
|
||||
def one(self) -> tuple[int, int]:
|
||||
return 2, 150000
|
||||
|
||||
return _Result()
|
||||
|
||||
|
||||
class TestCodInTransit:
|
||||
def test_excludes_received_refused_and_paid(self) -> None:
|
||||
session = _CapturingExecuteSession()
|
||||
result = asyncio.run(cod_in_transit(session)) # type: ignore[arg-type]
|
||||
sql = str(
|
||||
session.statement.compile(
|
||||
dialect=postgresql.dialect(), compile_kwargs={"literal_binds": True}
|
||||
)
|
||||
)
|
||||
|
||||
assert result == (2, 150000)
|
||||
assert "sum(orders.np_cod_amount_kopecks)" in sql
|
||||
assert "orders.is_deleted IS false" in sql
|
||||
assert "orders.np_cod_amount_kopecks IS NOT NULL" in sql
|
||||
assert (
|
||||
"orders.np_status_code NOT IN "
|
||||
"('9', '10', '11', '106', '102', '103', '105', '108', '2', '3')" in sql
|
||||
)
|
||||
assert "orders.np_payment_status IS DISTINCT FROM 'Payed'" in sql
|
||||
|
||||
Reference in New Issue
Block a user