Files

135 lines
4.9 KiB
Python
Raw Permalink 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.
"""全渠道与电商对接模型:
1. ChannelAccount 电商平台授权店铺配置(抖店、拼多多、1688 等)
2. ChannelOrder 外部拉取订单及本地销售订单映射
3. WebhookEvent 外部回调与事件分发日志
"""
from django.db import models
from apps.core.base_models import TenantScopedModel
class ChannelAccount(TenantScopedModel):
"""渠道授权店铺配置。"""
PLATFORM_CHOICES = [
("douyin", "抖音电商 / 抖店"),
("pinduoduo", "拼多多"),
("1688", "1688 阿里分销"),
("kuaishou", "快手小店"),
("custom", "自定义开放接口"),
]
platform = models.CharField(max_length=32, choices=PLATFORM_CHOICES, default="douyin")
shop_id = models.CharField(max_length=64, help_text="外部平台店铺ID")
shop_name = models.CharField(max_length=128, help_text="店铺名称")
app_key = models.CharField(max_length=128, blank=True, default="")
app_secret = models.CharField(max_length=255, blank=True, default="")
access_token = models.TextField(blank=True, default="")
refresh_token = models.TextField(blank=True, default="")
token_expires_at = models.DateTimeField(null=True, blank=True)
is_active = models.BooleanField(default=True)
# 业务映射默认值
default_warehouse = models.ForeignKey(
"inventory.Warehouse",
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name="+",
help_text="该店铺订单默认出库仓库",
)
default_customer = models.ForeignKey(
"partner.Customer",
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name="+",
help_text="该店铺归属的客户(挂账往来)",
)
class Meta:
db_table = "channel_account"
unique_together = [("tenant", "platform", "shop_id")]
verbose_name_plural = "电商店铺配置"
ordering = ["platform", "shop_name"]
def __str__(self):
return f"[{self.get_platform_display()}] {self.shop_name} ({self.shop_id})"
class ChannelOrder(TenantScopedModel):
"""外部渠道拉取的订单。"""
SYNC_STATUS_CHOICES = [
("pending", "待转单"),
("converted", "已转销售单"),
("failed", "转单失败"),
("ignored", "已忽略"),
]
channel_account = models.ForeignKey(
ChannelAccount,
on_delete=models.CASCADE,
related_name="orders",
)
external_order_id = models.CharField(max_length=128, help_text="外部平台订单号")
order_status = models.CharField(max_length=64, default="", help_text="外部平台订单状态(如 PAID, SHIPPED)")
order_amount = models.DecimalField(max_digits=18, decimal_places=4, default=0)
buyer_name = models.CharField(max_length=64, blank=True, default="")
buyer_phone = models.CharField(max_length=32, blank=True, default="")
receiver_address = models.CharField(max_length=255, blank=True, default="")
sync_status = models.CharField(max_length=16, choices=SYNC_STATUS_CHOICES, default="pending")
sync_error = models.TextField(blank=True, default="")
# 关联生成的本地销售单
sales_order = models.ForeignKey(
"sales.SalesOrder",
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name="channel_orders",
help_text="关联的内部销售订单",
)
raw_payload = models.JSONField(default=dict, blank=True, help_text="外部原始订单 JSON")
class Meta:
db_table = "channel_order"
unique_together = [("tenant", "channel_account", "external_order_id")]
verbose_name_plural = "渠道订单"
indexes = [
models.Index(fields=["tenant", "sync_status"]),
models.Index(fields=["tenant", "external_order_id"]),
]
ordering = ["-created_at"]
def __str__(self):
return f"{self.channel_account.shop_name} 订单: {self.external_order_id} [{self.sync_status}]"
class WebhookEvent(TenantScopedModel):
"""Webhook 回调与事件分发日志。"""
DIRECTION_CHOICES = [
("inbound", "外部推送回调"),
("outbound", "本系统向外推送"),
]
STATUS_CHOICES = [
("received", "已接收"),
("processed", "处理成功"),
("failed", "处理失败"),
]
direction = models.CharField(max_length=16, choices=DIRECTION_CHOICES, default="inbound")
event_type = models.CharField(max_length=64, help_text="事件类型,如 order.paid, stock.changed")
source = models.CharField(max_length=32, default="douyin", help_text="来源系统或平台")
payload = models.JSONField(default=dict, blank=True)
status = models.CharField(max_length=16, choices=STATUS_CHOICES, default="received")
error_message = models.TextField(blank=True, default="")
class Meta:
db_table = "channel_webhook_event"
verbose_name_plural = "Webhook事件日志"
ordering = ["-created_at"]