baseline: 批次A-D 成果 + membership 半成品(测试红)
This commit is contained in:
@@ -0,0 +1,86 @@
|
||||
"""全渠道与电商 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})
|
||||
Reference in New Issue
Block a user