|
7 | 7 | from admin_api.test.helpers import OrdersAdminApi |
8 | 8 | from admin_api.views.shop.orders import OrderAdminViewSet |
9 | 9 | from freezegun import freeze_time |
| 10 | +from model_bakery import baker |
10 | 11 | from rest_framework.fields import DateTimeField |
11 | 12 | from rest_framework.status import ( |
12 | 13 | HTTP_200_OK, |
@@ -101,6 +102,21 @@ def test_admin_list_filters_by_active_opr_category_group(api_client, ticket_prod |
101 | 102 | assert {row["id"] for row in response.json()["results"]} == {str(completed_order.id)} |
102 | 103 |
|
103 | 104 |
|
| 105 | +@pytest.mark.django_db |
| 106 | +def test_admin_list_filters_by_active_opr_event(api_client, ticket_product, non_ticket_product, order_factory): |
| 107 | + """`?event_id=` 가 해당 이벤트 카테고리의 상품을 가진 주문만 매칭한다.""" |
| 108 | + event = baker.make("event.Event", name="파이콘 한국 2026") |
| 109 | + ticket_product.category.event = event |
| 110 | + ticket_product.category.save() |
| 111 | + |
| 112 | + in_event_order = order_factory(status="completed") # ticket_product → event 연결됨 |
| 113 | + order_factory(status="completed", is_ticket=False) # non_ticket_product → event 없음 |
| 114 | + |
| 115 | + response = OrdersAdminApi(http_client=api_client).list({"event_id": str(event.id)}) |
| 116 | + assert response.status_code == HTTP_200_OK |
| 117 | + assert {row["id"] for row in response.json()["results"]} == {str(in_event_order.id)} |
| 118 | + |
| 119 | + |
104 | 120 | @pytest.mark.django_db |
105 | 121 | def test_admin_retrieve_returns_nested_payload(api_client, order_factory): |
106 | 122 | completed_order = order_factory(status="completed") |
@@ -226,7 +242,7 @@ def test_admin_export_returns_xlsx_filtering_refunded_per_include_flag( |
226 | 242 | ): |
227 | 243 | refunded_order = order_factory(status="refunded") |
228 | 244 | response = OrdersAdminApi(http_client=api_client).export( |
229 | | - {"product_ids": [str(ticket_product.id)], "include_refunded": include_refunded} |
| 245 | + {"product_id": str(ticket_product.id), "include_refunded": include_refunded} |
230 | 246 | ) |
231 | 247 | assert response.status_code == HTTP_200_OK |
232 | 248 | assert response.headers["Content-Type"] == "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" |
@@ -281,11 +297,49 @@ def test_admin_export_returns_xlsx_filtering_refunded_per_include_flag( |
281 | 297 | ] |
282 | 298 |
|
283 | 299 |
|
284 | | -@pytest.mark.parametrize("payload", [{}, {"product_ids": []}]) |
| 300 | +def _export_order_ids(response) -> set[str]: |
| 301 | + """export XLSX 응답의 '주문' 시트에서 주문 번호 집합을 추출.""" |
| 302 | + df = pandas.read_excel(BytesIO(b"".join(response.streaming_content)), sheet_name="주문", index_col=0, dtype=str) |
| 303 | + return set(df["주문 번호"].tolist()) if not df.empty else set() |
| 304 | + |
| 305 | + |
285 | 306 | @pytest.mark.django_db |
286 | | -def test_admin_export_rejects_missing_or_empty_product_ids(api_client, payload): |
287 | | - response = OrdersAdminApi(http_client=api_client).export(payload) |
288 | | - assert response.status_code == HTTP_400_BAD_REQUEST |
| 307 | +def test_admin_export_without_filters_returns_all_purchased_orders(api_client, ticket_product, order_factory): |
| 308 | + """필터 없이 호출하면 결제 완료 주문 전체를 내보낸다 (기본 include_refunded=false → 환불 제외).""" |
| 309 | + completed_order = order_factory(status="completed") |
| 310 | + order_factory(status="refunded") # include_refunded 기본 false → 제외 |
| 311 | + response = OrdersAdminApi(http_client=api_client).export() |
| 312 | + assert response.status_code == HTTP_200_OK |
| 313 | + # streaming_content 는 1회성 iterator — 한 번만 읽어 비교 (== 비교가 환불 주문 제외도 함께 검증). |
| 314 | + assert _export_order_ids(response) == {str(completed_order.id)} |
| 315 | + |
| 316 | + |
| 317 | +@pytest.mark.django_db |
| 318 | +def test_admin_export_scopes_by_event_id(api_client, ticket_product, non_ticket_product, order_factory): |
| 319 | + """`?event_id=` 가 해당 이벤트 카테고리의 상품을 가진 주문만 내보낸다.""" |
| 320 | + event = baker.make("event.Event", name="파이콘 한국 2026") |
| 321 | + ticket_product.category.event = event |
| 322 | + ticket_product.category.save() |
| 323 | + |
| 324 | + in_event_order = order_factory(status="completed") # ticket_product (event 연결됨) |
| 325 | + order_factory(status="completed", is_ticket=False) # non_ticket_product (event 없음) |
| 326 | + |
| 327 | + response = OrdersAdminApi(http_client=api_client).export({"event_id": str(event.id)}) |
| 328 | + assert response.status_code == HTTP_200_OK |
| 329 | + assert _export_order_ids(response) == {str(in_event_order.id)} |
| 330 | + |
| 331 | + |
| 332 | +@pytest.mark.django_db |
| 333 | +def test_admin_export_scopes_by_category_group_id(api_client, ticket_product, non_ticket_product, order_factory): |
| 334 | + """`?category_group_id=` 가 해당 그룹 상품을 가진 주문만 내보낸다.""" |
| 335 | + ticket_order = order_factory(status="completed") |
| 336 | + order_factory(status="completed", is_ticket=False) |
| 337 | + |
| 338 | + response = OrdersAdminApi(http_client=api_client).export( |
| 339 | + {"category_group_id": str(ticket_product.category.group_id)} |
| 340 | + ) |
| 341 | + assert response.status_code == HTTP_200_OK |
| 342 | + assert _export_order_ids(response) == {str(ticket_order.id)} |
289 | 343 |
|
290 | 344 |
|
291 | 345 | @pytest.mark.django_db |
|
0 commit comments