Files
dealerhub/backend/tests/test_channel.py
T

133 lines
4.2 KiB
Python

"""全渠道与电商对接集成测试。"""
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