"""全渠道与电商对接集成测试。""" import pytest from decimal import Decimal from model_bakery import baker from rest_framework.test import APIClient from rest_framework_simplejwt.tokens import RefreshToken from apps.catalog.models import Product from apps.inventory.models import Warehouse from apps.partner.models import Customer from apps.channel.models import ChannelAccount, ChannelOrder, WebhookEvent from apps.channel import services as channel_services @pytest.fixture def auth_client(db, user, tenant): client = APIClient() refresh = RefreshToken.for_user(user) client.credentials( HTTP_AUTHORIZATION=f"Bearer {refresh.access_token}", HTTP_X_TENANT_ID=tenant.code, ) return client @pytest.mark.django_db def test_sync_and_convert_channel_order(tenant): wh = baker.make(Warehouse, tenant=tenant, code="WH_ONLINE", name="电商仓") cust = baker.make(Customer, tenant=tenant, code="C_ONLINE", name="抖音买家总客户") prod = baker.make(Product, tenant=tenant, code="P_DOUYIN", name="抖音热销饮品", sale_price=Decimal("45.00")) account = ChannelAccount.objects.create( tenant=tenant, platform="douyin", shop_id="DY88888", shop_name="旗舰店", default_warehouse=wh, default_customer=cust, ) # 模拟外部订单 raw_payload = { "external_order_id": "DY-ORD-10001", "order_status": "PAID", "order_amount": "90.00", "buyer_name": "李四", "buyer_phone": "13911112222", "receiver_address": "北京市海淀区", "items": [ {"product_code": "P_DOUYIN", "quantity": "2", "unit_price": "45.00"} ], } corder = ChannelOrder.objects.create( tenant=tenant, channel_account=account, external_order_id="DY-ORD-10001", order_status="PAID", order_amount=Decimal("90.00"), buyer_name="李四", buyer_phone="13911112222", raw_payload=raw_payload, sync_status="pending", ) # 转单为内部销售单 sales_order = channel_services.convert_channel_order_to_sales_order(corder) assert sales_order is not None assert sales_order.state == "confirmed" assert sales_order.total_amount == Decimal("90.00") assert sales_order.lines.count() == 1 assert sales_order.customer == cust corder.refresh_from_db() assert corder.sync_status == "converted" assert corder.sales_order == sales_order @pytest.mark.django_db def test_channel_inbound_webhook(tenant): wh = baker.make(Warehouse, tenant=tenant, code="WH_MALL") cust = baker.make(Customer, tenant=tenant, code="C_MALL") prod = baker.make(Product, tenant=tenant, code="P_HOT", sale_price=Decimal("100.00")) account = ChannelAccount.objects.create( tenant=tenant, platform="douyin", shop_id="SHOP_WB_01", shop_name="抖音小店A", default_warehouse=wh, default_customer=cust, ) payload = { "shop_id": "SHOP_WB_01", "external_order_id": "WB-DY-9999", "order_amount": "200.00", "buyer_name": "王五", "items": [ {"product_code": "P_HOT", "quantity": "2", "unit_price": "100.00"} ], } event = channel_services.handle_inbound_webhook( tenant=tenant, platform="douyin", event_type="order.paid", payload=payload, ) assert event.status == "processed" assert ChannelOrder.objects.filter(tenant=tenant, external_order_id="WB-DY-9999").exists() @pytest.mark.django_db def test_channel_api_endpoints(auth_client, tenant): # 1. 创建店铺 payload = { "platform": "douyin", "shop_id": "DY_TEST_01", "shop_name": "测试抖店", "app_key": "key_123", } r = auth_client.post("/api/v1/channel/accounts/", payload, format="json") assert r.status_code == 201 acc_id = r.json()["id"] # 2. 触发同步订单 action baker.make(Product, tenant=tenant, code="P001", sale_price=Decimal("10")) r2 = auth_client.post(f"/api/v1/channel/accounts/{acc_id}/sync-orders/", {"auto_convert": True}, format="json") assert r2.status_code == 200 assert r2.json()["ok"] is True