Files
dealerhub/backend/apps/channel/views.py
T

87 lines
3.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""全渠道与电商 ViewSets:
1. ChannelAccountViewSet: 店铺授权管理、action sync_orders 触发拉单
2. ChannelOrderViewSet: 渠道订单列表、action convert 手动转单
3. WebhookViewSet: 接收外部 Webhook 推送
"""
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.exceptions import ValidationError
from asgiref.sync import sync_to_async
from adrf.viewsets import ViewSet
from apps.core.viewset import BaseTenantViewSet
from .models import ChannelAccount, ChannelOrder, WebhookEvent
from .serializers import ChannelAccountSerializer, ChannelOrderSerializer, WebhookEventSerializer
from . import services as channel_services
class ChannelAccountViewSet(BaseTenantViewSet):
model = ChannelAccount
serializer_class = ChannelAccountSerializer
search_fields = ["shop_id", "shop_name", "platform"]
@action(detail=True, methods=["post"], url_path="sync-orders")
async def sync_orders(self, request, pk=None):
"""主动从该电商渠道拉取最新订单并自动转内部销售单。"""
tenant = await self.get_tenant()
try:
account = await sync_to_async(self.model.objects.get)(tenant=tenant, pk=pk)
except self.model.DoesNotExist:
return Response({"detail": "店铺配置不存在"}, status=status.HTTP_404_NOT_FOUND)
auto_convert = request.data.get("auto_convert", True)
result = await sync_to_async(channel_services.sync_channel_orders)(account, auto_convert=auto_convert)
return Response({"ok": True, "result": result})
class ChannelOrderViewSet(BaseTenantViewSet):
model = ChannelOrder
serializer_class = ChannelOrderSerializer
search_fields = ["external_order_id", "buyer_name", "buyer_phone"]
@action(detail=True, methods=["post"], url_path="convert")
async def convert(self, request, pk=None):
"""将指定的外部渠道订单转换为内部销售订单。"""
tenant = await self.get_tenant()
try:
corder = await sync_to_async(self.model.objects.get)(tenant=tenant, pk=pk)
except self.model.DoesNotExist:
return Response({"detail": "订单不存在"}, status=status.HTTP_404_NOT_FOUND)
try:
so = await sync_to_async(channel_services.convert_channel_order_to_sales_order)(corder)
return Response({
"ok": True,
"sales_order_id": so.id,
"sales_order_no": so.bill_no,
})
except Exception as e:
return Response({"detail": str(e)}, status=status.HTTP_400_BAD_REQUEST)
class WebhookViewSet(ViewSet):
"""接收外部平台的 Webhook 实时通知(如抖店支付推送)。"""
async def get_tenant(self):
from apps.core.viewset import resolve_tenant
from django.conf import settings
code = self.request.META.get("HTTP_X_TENANT_ID", settings.TENANT_DEFAULT)
return await sync_to_async(resolve_tenant)(code)
@action(detail=False, methods=["post"], url_path="inbound")
async def inbound(self, request):
tenant = await self.get_tenant()
if not tenant:
raise ValidationError({"tenant": "无法识别租户"})
platform = request.data.get("platform", "douyin")
event_type = request.data.get("event_type", "order.paid")
payload = request.data.get("payload", {})
event = await sync_to_async(channel_services.handle_inbound_webhook)(
tenant, platform=platform, event_type=event_type, payload=payload
)
return Response({"ok": True, "event_id": event.id, "status": event.status})