Files
along_django/peizhi/models.py

877 lines
39 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.
from django.db import models
class Lunbo(models.Model):
tupian_url = models.CharField(max_length=500, null=True, blank=True, verbose_name='轮播图片URL')
leixing = models.IntegerField(null=True, blank=True, verbose_name='图片类型:1轮播2个人中心背景')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更改时间')
class Meta:
db_table = 'lunbo'
verbose_name = '轮播'
verbose_name_plural = '轮播'
# 不要索引!数据量太小
class Gonggao(models.Model):
leixing = models.IntegerField(null=True, blank=True, verbose_name='公告类型')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更改时间')
jieshao = models.TextField(null=True, blank=True, verbose_name='公告介绍')
class Meta:
db_table = 'gonggao'
verbose_name = '公告'
verbose_name_plural = '公告'
# 不要索引!数据量太小
class Qunpeizhi(models.Model):
peizhiid = models.IntegerField(null=True, blank=True, verbose_name='群类型:1.打手 2.管事')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更改时间')
neirong = models.CharField(max_length=200, null=True, blank=True, verbose_name='群介绍')
qunid = models.CharField(max_length=100, null=True, blank=True, verbose_name='群id')
jieshao = models.CharField(max_length=200, null=True, blank=True, verbose_name='介绍')
class Meta:
db_table = 'qunpeizhi'
class Tupianpeizhi(models.Model):
tupian = models.CharField(max_length=500, null=True, blank=True, verbose_name='配置图片URL')
leixing = models.PositiveIntegerField(null=True, blank=True, verbose_name='提现类型1:打手规则图片2默认头像图片')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更改时间')
fangwen_cishu = models.PositiveIntegerField(default=0, verbose_name='访问次数') # 新增字段
class Meta:
db_table = 'tupianpeizhi'
verbose_name = '配置图片'
verbose_name_plural = '配置图片'
class Szjilu(models.Model):
id = models.AutoField(primary_key=True, verbose_name='记录ID')
zongsy = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, verbose_name='总收益')
zongls = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, verbose_name='总流水')
zongzc = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, verbose_name='总支出')
jrzc = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, verbose_name='今日支出')
jrls = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, verbose_name='今日流水')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更改时间')
class Meta:
db_table = 'szjilu'
verbose_name = '收支记录'
verbose_name_plural = '收支记录'
# models/shangjia_moban.py
from django.db import models
class ShangjiaMoban(models.Model):
"""商家订单模板表 - 存储商家创建的订单模板"""
# 主键ID自动递增
id = models.AutoField(primary_key=True, verbose_name='模板ID')
# 关联字段
yonghu_id = models.CharField(max_length=7, db_index=True, verbose_name='用户ID')
leixing_id = models.PositiveIntegerField(db_index=True, verbose_name='商品类型ID')
# 模板内容
moban_jieshao = models.CharField(max_length=500, verbose_name='模板介绍')
jiage = models.DecimalField(
max_digits=10,
decimal_places=2,
verbose_name='模板价格',
help_text='单位:元'
)
# 统计字段
fabu_shuliang = models.PositiveIntegerField(default=0, verbose_name='发布数量')
# 时间字段
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
yongjin_qiangdan = models.BooleanField(default=False, verbose_name='是否开启佣金抢单')
yongjin_jiage = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True, verbose_name='佣金价格')
chenghao_id = models.IntegerField(null=True, blank=True, verbose_name='关联称号ID')
class Meta:
db_table = 'shangjia_moban'
verbose_name = '商家订单模板'
verbose_name_plural = verbose_name
indexes = [
# 高频查询组合索引
models.Index(fields=['yonghu_id', 'leixing_id']),
models.Index(fields=['yonghu_id', 'leixing_id','id']),
]
# 同一个商家同一类型下模板介绍不能重复(允许修改)
unique_together = ['yonghu_id', 'leixing_id', 'moban_jieshao']
def __str__(self):
return f"模板{self.id}-{self.yonghu_id}"
# models/shangjia_lianjie.py
from django.db import models
class ShangjiaLianjie(models.Model):
"""商家链接存储表 - 存储生成的派单链接"""
# 主键ID自动递增
id = models.AutoField(primary_key=True, verbose_name='链接ID')
# 关联字段
yonghu_id = models.CharField(max_length=7, db_index=True, verbose_name='用户ID')
leixing_id = models.PositiveIntegerField(db_index=True, verbose_name='商品类型ID')
moban_id = models.PositiveIntegerField(db_index=True, verbose_name='模板ID')
# 链接核心数据
lianjie = models.CharField(max_length=500, unique=True, verbose_name='链接地址')
#lianjie_token = models.CharField(max_length=32, unique=True, db_index=True, verbose_name='链接Token')
# 订单关联(生成订单后更新)
dingdan_id = models.CharField(max_length=32, null=True, blank=True, db_index=True, verbose_name='订单ID')
# 使用状态
is_used = models.BooleanField(default=False, verbose_name='是否已使用', db_index=True)
#shiyong_time = models.DateTimeField(null=True, blank=True, verbose_name='使用时间')
# 使用者信息
shiyongzhe_ip = models.CharField(max_length=50, null=True, blank=True, verbose_name='使用者IP')
#shiyongzhe_info = models.TextField(null=True, blank=True, verbose_name='使用者信息')
# 链接控制
#shiyong_cishu = models.PositiveIntegerField(default=1, verbose_name='可使用次数')
#yixiang_cishu = models.PositiveIntegerField(default=0, verbose_name='已使用次数')
youxiao_shijian = models.DateTimeField(null=True, blank=True, verbose_name='有效截止时间')
# 安全字段
#anquan_ma = models.CharField(max_length=100, null=True, blank=True, verbose_name='安全码')
# 新增 Token 字段
lianjie_token = models.CharField(
max_length=32,
unique=True,
db_index=True,
verbose_name='链接Token',
null=True,
blank=True # 先设置为可选,后面再设为必填
)
# 时间字段
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
# 上一个链接的ID可选记录订单被更换前的链接
previous_lianjie_id = models.PositiveIntegerField(
null=True,
blank=True,
db_index=True,
verbose_name='上一个链接ID'
)
# 上一个订单的ID可选记录被更换的旧订单ID
previous_dingdan_id = models.CharField(
max_length=32,
null=True,
blank=True,
db_index=True,
verbose_name='上一个订单ID'
)
# 上一个链接的ID可选记录订单被更换前的链接
previous_lianjie_id = models.PositiveIntegerField(
null=True,
blank=True,
db_index=True,
verbose_name='上一个链接ID'
)
# 上一个订单的ID可选记录被更换的旧订单ID
previous_dingdan_id = models.CharField(
max_length=32,
null=True,
blank=True,
db_index=True,
verbose_name='上一个订单ID'
)
class Meta:
db_table = 'shangjia_lianjie'
verbose_name = '商家链接'
verbose_name_plural = verbose_name
indexes = [
# 高频查询组合索引
models.Index(fields=['yonghu_id', 'moban_id','leixing_id']),
models.Index(fields=['lianjie_token']),
#models.Index(fields=['lianjie_token']),
models.Index(fields=['dingdan_id']),
#models.Index(fields=['moban_id']),
#models.Index(fields=['create_time']),
#models.Index(fields=['youxiao_shijian', 'is_used']),
]
#ordering = ['-create_time']
def __str__(self):
return f"链接{self.id}-{self.yonghu_id}"
class TixianQuotaDefault(models.Model):
"""
默认每日提现限额表
"""
id = models.AutoField(primary_key=True)
leixing = models.IntegerField(
choices=[(1, '打手'), (2, '管事'), (3, '组长'),
(4, '打手总额'), (5, '管事总额'), (6, '组长总额'),
(7, '考核官总额'), (8, '打手押金总额'), (9, '商家余额总额')],
unique=True,
verbose_name='用户类型'
)
default_quota = models.DecimalField(
max_digits=10,
decimal_places=2,
default=20.00,
verbose_name='默认每日提现限额(元)'
)
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
class Meta:
db_table = 'tixian_quota_default'
verbose_name = '默认提现限额'
verbose_name_plural = verbose_name
def __str__(self):
return f"{self.get_leixing_display()} 默认限额: {self.default_quota}"
class WithdrawConfig(models.Model):
"""
提现模式配置表
- mode = 1: 自动提现(前端展示收款码模式)
- mode = 2: 手动提现(前端展示微信零钱模式)
默认值为 2手动打款没有记录时前端也按默认 2 处理
"""
MODE_CHOICES = (
(1, '自动提现'), # 对应前端模式一
(2, '手动提现'), # 对应前端模式二
)
mode = models.IntegerField(
choices=MODE_CHOICES,
default=2,
verbose_name='提现模式'
)
dongjie_quanju_enabled = models.BooleanField(default=False, verbose_name='全员冻结总开关')
created_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
updated_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
class Meta:
db_table = 'withdraw_config'
verbose_name = '提现模式配置'
verbose_name_plural = verbose_name
def __str__(self):
return f'提现模式: {"自动" if self.mode == 1 else "手动"}'
# apps/club/models.py
from django.db import models
class Club(models.Model):
"""合作俱乐部/平台信息表"""
# 自己的俱乐部ID6位字符
club_id = models.CharField(max_length=6, db_index=True, verbose_name='本俱乐部ID')
# 对方的俱乐部ID6位字符
partner_club_id = models.CharField(max_length=6, unique= True,verbose_name='对方俱乐部ID')
# 是否开启平台互通(双方互相同意才可传递订单)
is_interop_enabled = models.BooleanField(default=False, verbose_name='是否开启平台互通')
# 是否同意接收对方订单(对方同意我方发单,但接收订单需我方同意)
is_receive_enabled = models.BooleanField(default=False, verbose_name='是否同意接收对方订单')
# 打手分红费率默认100%,即原金额,对方平台打手分成 = 我方打手分成 × 费率)
dashou_rate = models.DecimalField(max_digits=5, decimal_places=4, default=1.0000, verbose_name='打手分红费率')
# 新增字段接收对方订单时打手分红费率默认100%
receive_rate = models.DecimalField(max_digits=5, decimal_places=4, default=1.0000, verbose_name='接收打手分红费率')
# 对方服务器域名(完整 URL如 https://api.partner.com
partner_domain = models.URLField(max_length=200, blank=True, verbose_name='对方服务器域名')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
class Meta:
db_table = 'club'
verbose_name = '俱乐部'
verbose_name_plural = '俱乐部'
indexes = [
models.Index(fields=['club_id']),
models.Index(fields=['partner_club_id']),
]
class OrderTypeMapping(models.Model):
"""对方订单类型 → 我方订单类型 映射表"""
partner_club_id = models.CharField(max_length=6, db_index=True, verbose_name='对方俱乐部ID')
partner_type_id = models.PositiveIntegerField(verbose_name='对方订单类型ID')
partner_type_name = models.CharField(max_length=100, verbose_name='对方订单类型名称')
our_type_id = models.PositiveIntegerField(verbose_name='我方订单类型ID')
our_type_name = models.CharField(max_length=100, verbose_name='我方订单类型名称')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
class Meta:
db_table = 'order_type_mapping'
verbose_name = '订单类型映射'
verbose_name_plural = '订单类型映射'
unique_together = (('partner_club_id', 'partner_type_id'),)
class ClubConfig(models.Model):
"""
俱乐部配置信息表
存储俱乐部我方或对方的详细配置如昵称、头像、API密钥等
"""
# 俱乐部ID6位字符与 Club 表中的 club_id 或 partner_club_id 对应)
club_id = models.CharField(max_length=6, db_index=True, verbose_name='俱乐部ID')
# 俱乐部昵称
club_nickname = models.CharField(max_length=50, blank=True, default='', verbose_name='俱乐部昵称')
# 俱乐部头像地址URL
club_avatar = models.CharField(max_length=500, blank=True, default='', verbose_name='俱乐部头像地址')
# 俱乐部后台域名用于API请求
backend_domain = models.CharField(max_length=200, blank=True, default='', verbose_name='后台域名')
# 聊天API密钥
chat_api_key = models.CharField(max_length=200, blank=True, default='', verbose_name='聊天API密钥')
# 聊天API ID
chat_api_id = models.CharField(max_length=200, blank=True, default='', verbose_name='聊天API ID')
# 客服路径
customer_service_api_url = models.CharField(max_length=200, blank=True, default='', verbose_name='客服API URL')
customer_service_corp_id = models.CharField(max_length=100, blank=True, default='', verbose_name='客服企业ID')
# 存储桶域名如腾讯云COS、阿里云OSS的访问域名
storage_bucket_domain = models.CharField(max_length=500, blank=True, default='', verbose_name='存储桶域名')
storage_bucket_name = models.CharField(max_length=100, blank=True, default='', verbose_name='存储桶名称')
# 标识是我方还是对方俱乐部1=我方0=对方默认0
is_self = models.SmallIntegerField(
choices=((0, '对方'), (1, '我方')),
default=0,
db_index=True,
verbose_name='是否我方俱乐部'
)
# 创建时间
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
# 更新时间
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
class Meta:
db_table = 'club_config'
verbose_name = '俱乐部配置'
verbose_name_plural = '俱乐部配置'
# 联合唯一约束同一个俱乐部ID只能有一条记录无论我方对方若需要分开则可不加
# 但通常一个俱乐部只会存在一种身份,所以加联合唯一约束更安全
unique_together = [['club_id']] # 确保每个club_id只有一条配置记录
def __str__(self):
return f"{self.club_nickname or self.club_id} ({'我方' if self.is_self else '对方'})"
from django.db import models
class AccountPermission(models.Model):
"""账号权限表:记录每个账号拥有的权限及开关状态"""
account_id = models.CharField(max_length=11, db_index=True, verbose_name='账号ID')
permission_code = models.IntegerField(verbose_name='权限代码')
is_enabled = models.BooleanField(default=False, verbose_name='是否开启')
class Meta:
db_table = 'account_permission'
verbose_name = '账号权限'
verbose_name_plural = '账号权限'
unique_together = [['account_id', 'permission_code']] # 一个账号的同一权限只能有一条记录
def __str__(self):
return f"{self.account_id} 权限{self.permission_code}: {'开启' if self.is_enabled else '关闭'}"
# apps/dingdan/models.py (添加新模型)
class DailyDispatchStat(models.Model):
"""
每日派单统计表
记录每天向各合作俱乐部派单的数据,用于替代俱乐部表中的累计字段。
"""
# 日期相关字段(便于快速筛选)
date = models.DateField(verbose_name='统计日期', db_index=True)
year = models.PositiveSmallIntegerField(verbose_name='年份')
month = models.PositiveSmallIntegerField(verbose_name='月份')
day = models.PositiveSmallIntegerField(verbose_name='日期')
# 派单方向1=我方派单我方订单被对方抢单2=对方派单(对方订单被我方抢单)
direction = models.PositiveSmallIntegerField(choices=[(1, '我方派单'), (2, '对方派单')], verbose_name='派单方向')
# 对方俱乐部ID
partner_club_id = models.CharField(max_length=6, db_index=True, verbose_name='对方俱乐部ID')
# 派单数
dispatch_count = models.PositiveIntegerField(default=0, verbose_name='派单数')
# 派单总额(打手分成 * 费率)
dispatch_amount = models.DecimalField(max_digits=12, decimal_places=2, default=0.00, verbose_name='派单总额')
# 抢单统计(我方实际抢到的对方派单数/金额)
claimed_count = models.PositiveIntegerField(default=0, verbose_name='抢单数')
claimed_amount = models.DecimalField(max_digits=12, decimal_places=2, default=0.00, verbose_name='抢单总额')
# 成交订单数(预留,当前暂不更新)
success_count = models.PositiveIntegerField(default=0, verbose_name='成交订单数')
# 成交总额(预留)
success_amount = models.DecimalField(max_digits=12, decimal_places=2, default=0.00, verbose_name='成交总额')
# 时间戳
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
class Meta:
db_table = 'daily_dispatch_stat'
verbose_name = '每日派单统计'
verbose_name_plural = verbose_name
indexes = [
models.Index(fields=['year', 'month', 'day', 'direction', 'partner_club_id']),
models.Index(fields=['date']),
]
def __str__(self):
return f"{self.date} - 方向{self.direction} - 俱乐部{self.partner_club_id} - 派单{self.dispatch_count}"
# apps/dingdan/models.py (新增模型)
class DailyIncomeStat(models.Model):
"""
每日收入统计表
记录平台每天通过微信支付获得的总收入和总笔数
"""
# 日期相关字段(便于快速筛选和分组)
date = models.DateField(verbose_name='统计日期', db_index=True, unique=True)
year = models.PositiveSmallIntegerField(verbose_name='年份')
month = models.PositiveSmallIntegerField(verbose_name='月份')
day = models.PositiveSmallIntegerField(verbose_name='日期')
# 收入统计
total_amount = models.DecimalField(max_digits=12, decimal_places=2, default=0.00, verbose_name='总收入金额')
total_count = models.PositiveIntegerField(default=0, verbose_name='总收入笔数')
# 时间戳
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
class Meta:
db_table = 'daily_income_stat'
verbose_name = '每日收入统计'
verbose_name_plural = verbose_name
indexes = [
models.Index(fields=['date']),
models.Index(fields=['year', 'month', 'day']),
]
def __str__(self):
return f"{self.date} - 收入{self.total_amount}元 - {self.total_count}"
# apps/dingdan/models.py
class DailyPayoutStat(models.Model):
"""
每日出款统计表
记录平台每天通过提现/结算等方式的出款总额和总笔数
"""
date = models.DateField(verbose_name='统计日期', db_index=True, unique=True)
year = models.PositiveSmallIntegerField(verbose_name='年份')
month = models.PositiveSmallIntegerField(verbose_name='月份')
day = models.PositiveSmallIntegerField(verbose_name='日期')
total_amount = models.DecimalField(max_digits=12, decimal_places=2, default=0.00, verbose_name='出款总额')
total_count = models.PositiveIntegerField(default=0, verbose_name='出款总笔数')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
class Meta:
db_table = 'daily_payout_stat'
verbose_name = '每日出款统计'
verbose_name_plural = verbose_name
indexes = [
models.Index(fields=['date']),
models.Index(fields=['year', 'month', 'day']),
]
def __str__(self):
return f"{self.date} - 出款{self.total_amount}元 - {self.total_count}"
from django.db import models
class PopupPage(models.Model):
page_key = models.CharField(max_length=50, unique=True, db_index=True, verbose_name='页面标识')
name = models.CharField(max_length=100, verbose_name='页面名称')
description = models.TextField(blank=True, verbose_name='描述')
is_active = models.BooleanField(default=True, verbose_name='是否启用')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
ignore_user_mute = models.BooleanField(default=False, verbose_name='忽略用户今日屏蔽')
class Meta:
db_table = 'popup_page'
verbose_name = '弹窗页面'
verbose_name_plural = '弹窗页面'
def __str__(self):
return f'{self.name} ({self.page_key})'
class PopupConfig(models.Model):
STRATEGY_CHOICES = (
('once', '仅一次'),
('daily', '每日'),
('weekly', '每周'),
('monthly', '每月'),
('yearly', '每年'),
('always', '始终'),
('count', '周期内次数限制'),
)
page = models.ForeignKey(PopupPage, on_delete=models.CASCADE, related_name='popups')
popup_id = models.CharField(max_length=50, verbose_name='弹窗唯一ID')
title = models.CharField(max_length=200, blank=True, verbose_name='标题(后台用)')
description = models.TextField(blank=True, verbose_name='描述(后台用)')
strategy_type = models.CharField(max_length=20, choices=STRATEGY_CHOICES, default='once')
max_count = models.PositiveIntegerField(default=1, verbose_name='周期内最大展示次数')
reset_interval = models.CharField(max_length=20, blank=True,
choices=(('day',''),('week',''),('month',''),('year','')),
verbose_name='重置周期count类型时使用')
duration = models.PositiveIntegerField(default=0, verbose_name='强制阅读秒数0=无强制)')
force_even_muted = models.BooleanField(default=False, verbose_name='强制弹出(忽略用户今日屏蔽)')
sort_order = models.PositiveIntegerField(default=0, verbose_name='展示顺序')
is_active = models.BooleanField(default=True, verbose_name='是否启用')
start_time = models.DateTimeField(null=True, blank=True, verbose_name='生效开始时间')
end_time = models.DateTimeField(null=True, blank=True, verbose_name='生效结束时间')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'popup_config'
verbose_name = '弹窗配置'
verbose_name_plural = '弹窗配置'
unique_together = ('page', 'popup_id')
ordering = ['sort_order', 'id']
def __str__(self):
return f'{self.page.name} - {self.popup_id}'
class PopupImage(models.Model):
popup_config = models.ForeignKey(PopupConfig, on_delete=models.CASCADE, related_name='images')
image_url = models.CharField(max_length=500, verbose_name='图片相对路径')
text = models.TextField(blank=True, verbose_name='图片上方文字')
sort_order = models.PositiveIntegerField(default=0, verbose_name='展示顺序')
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
db_table = 'popup_image'
verbose_name = '弹窗图片'
verbose_name_plural = '弹窗图片'
ordering = ['sort_order', 'id']
def __str__(self):
return f'{self.popup_config.popup_id} - 图片{self.sort_order}'
class HuashuConfig(models.Model):
"""小程序话术/确认弹窗配置(聊天发图、客服欢迎/自动回复、商家派单等)"""
SCENE_CHAT_IMAGE_CONFIRM = 'chat_image_confirm'
SCENE_CS_WELCOME = 'cs_welcome'
SCENE_CS_AUTO_REPLY = 'cs_auto_reply'
SCENE_MERCHANT_DISPATCH = 'merchant_dispatch_confirm'
SCENE_CHOICES = (
(SCENE_CHAT_IMAGE_CONFIRM, '聊天发图确认'),
(SCENE_CS_WELCOME, '客服欢迎语'),
(SCENE_CS_AUTO_REPLY, '客服自动回复'),
(SCENE_MERCHANT_DISPATCH, '商家派单确认'),
)
ITEM_CONFIRM = 'confirm_modal'
ITEM_TEXT = 'text_display'
ITEM_AUTO_REPLY = 'auto_reply'
ITEM_TYPE_CHOICES = (
(ITEM_CONFIRM, '确认弹窗'),
(ITEM_TEXT, '纯文本展示'),
(ITEM_AUTO_REPLY, '自动回复'),
)
MATCH_CONTAINS = 'contains'
MATCH_EXACT = 'exact'
MATCH_MODE_CHOICES = (
(MATCH_CONTAINS, '包含匹配'),
(MATCH_EXACT, '精确匹配'),
)
scene_key = models.CharField(max_length=50, choices=SCENE_CHOICES, db_index=True, verbose_name='场景标识')
item_type = models.CharField(max_length=20, choices=ITEM_TYPE_CHOICES, verbose_name='条目类型')
title = models.CharField(max_length=200, blank=True, default='', verbose_name='标题')
content = models.TextField(verbose_name='正文内容')
confirm_text = models.CharField(max_length=50, blank=True, default='我知道了', verbose_name='确认按钮文案')
cancel_text = models.CharField(max_length=50, blank=True, default='取消', verbose_name='取消按钮文案')
keywords = models.JSONField(default=list, blank=True, verbose_name='触发关键词(JSON数组)')
match_mode = models.CharField(
max_length=20, choices=MATCH_MODE_CHOICES, default=MATCH_CONTAINS, verbose_name='匹配模式'
)
priority = models.IntegerField(default=0, verbose_name='优先级(越大越先匹配)')
is_active = models.BooleanField(default=True, verbose_name='是否启用')
sort_order = models.IntegerField(default=0, verbose_name='排序')
created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')
class Meta:
db_table = 'huashu_config'
verbose_name = '话术配置'
verbose_name_plural = '话术配置'
ordering = ['scene_key', '-priority', 'sort_order', 'id']
def __str__(self):
return f'{self.get_scene_key_display()} - {self.get_item_type_display()}'
class XcxSysPeizhi(models.Model):
"""小程序/微信系统配置(单例表,后台可改,优先于 settings.py"""
weixin_appid = models.CharField(max_length=64, blank=True, default='', verbose_name='小程序AppID')
weixin_secret = models.CharField(max_length=128, blank=True, default='', verbose_name='小程序Secret')
weixin_official_appid = models.CharField(max_length=64, blank=True, default='', verbose_name='服务号AppID')
weixin_official_secret = models.CharField(max_length=128, blank=True, default='', verbose_name='服务号Secret')
weixin_official_token = models.CharField(max_length=128, blank=True, default='', verbose_name='服务号Token')
weixin_official_encoding_aes_key = models.CharField(
max_length=128, blank=True, default='', verbose_name='服务号EncodingAESKey'
)
weixin_template_id = models.CharField(max_length=128, blank=True, default='', verbose_name='模板消息ID')
weixin_template_max_per_minute = models.PositiveIntegerField(default=950, verbose_name='模板消息每分钟上限')
weixin_template_batch_size = models.PositiveIntegerField(default=100, verbose_name='模板消息批大小')
weixin_broadcast_enabled = models.BooleanField(default=True, verbose_name='服务号广播开关')
weixin_broadcast_workers = models.PositiveIntegerField(default=30, verbose_name='广播并发线程数')
weixin_mchid = models.CharField(max_length=32, blank=True, default='', verbose_name='微信支付商户号')
weixin_shanghu_miyao = models.CharField(max_length=128, blank=True, default='', verbose_name='商户密钥')
weixin_notify_url = models.CharField(max_length=300, blank=True, default='', verbose_name='支付回调URL')
weixin_cert_path = models.CharField(max_length=500, blank=True, default='', verbose_name='退款证书路径')
weixin_key_path = models.CharField(max_length=500, blank=True, default='', verbose_name='退款密钥路径')
# 支付专用商户(与提现收款 WechatPayMchConfig / 旧 weixin_* 分离)
pay_mch_id = models.CharField(max_length=32, blank=True, default='', verbose_name='支付商户号')
pay_api_v2_key = models.CharField(max_length=128, blank=True, default='', verbose_name='支付APIv2密钥')
pay_api_v3_key = models.CharField(max_length=128, blank=True, default='', verbose_name='支付APIv3密钥')
pay_notify_url = models.CharField(max_length=300, blank=True, default='', verbose_name='支付回调URL(支付商户)')
pay_cert_path = models.CharField(max_length=500, blank=True, default='', verbose_name='支付退款证书路径')
pay_key_path = models.CharField(max_length=500, blank=True, default='', verbose_name='支付退款密钥路径')
pay_cert_serial_no = models.CharField(max_length=128, blank=True, default='', verbose_name='支付商户证书序列号')
notify_base_url = models.CharField(
max_length=300, blank=True, default='https://wenhe.nmslb.com/hqhd', verbose_name='业务回调根URL'
)
# 点单页 /shangpin/shangpinhuoqu 按此值筛选类型/专区/商品的 shenhezhuangtai
shangpin_shenhe_mode = models.PositiveSmallIntegerField(
default=2,
verbose_name='点单商品展示模式',
help_text='1=正常运营(shenhezhuangtai=1)2=审核专用(shenhezhuangtai=2)',
)
shangjia_paifa_jiage_min = models.DecimalField(
max_digits=10, decimal_places=2, default=10.00, verbose_name='商家派单最低金额(元)',
)
shangjia_paifa_jiage_max = models.DecimalField(
max_digits=10, decimal_places=2, default=10000.00, verbose_name='商家派单最高金额(元)',
)
# 商家派单「要求接单员押金」金额范围yaoqiuleixing=2 / commission
shangjia_paifa_yajin_min = models.DecimalField(
max_digits=10, decimal_places=2, default=0.10, verbose_name='派单押金要求最低(元)',
)
shangjia_paifa_yajin_max = models.DecimalField(
max_digits=10, decimal_places=2, default=10000.00, verbose_name='派单押金要求最高(元)',
)
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
class Meta:
db_table = 'xcx_sys_peizhi'
verbose_name = '小程序系统配置'
verbose_name_plural = verbose_name
class XcxPageZiyuan(models.Model):
"""小程序页面背景图/图标(按组+键唯一)"""
ziyuan_zu = models.CharField(max_length=32, db_index=True, verbose_name='资源组')
ziyuan_key = models.CharField(max_length=64, verbose_name='资源键')
ziyuan_path = models.CharField(max_length=500, verbose_name='OSS相对路径')
miaoshu = models.CharField(max_length=200, blank=True, default='', verbose_name='说明')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
class Meta:
db_table = 'xcx_page_ziyuan'
verbose_name = '小程序页面资源'
verbose_name_plural = verbose_name
unique_together = [['ziyuan_zu', 'ziyuan_key']]
indexes = [models.Index(fields=['ziyuan_zu'])]
def __str__(self):
return f'{self.ziyuan_zu}.{self.ziyuan_key}'
class XcxXieyi(models.Model):
"""小程序用户协议配置"""
MODE_IMAGE = 1
MODE_TEXT = 2
MODE_CHOICES = (
(MODE_IMAGE, '纯图片'),
(MODE_TEXT, '文字'),
)
SHENFEN_CHOICES = (
('dashou', '打手'),
('guanshi', '管事'),
('zuzhang', '组长'),
('shangjia', '商家'),
('normal', '点单老板'),
)
title = models.CharField(max_length=200, verbose_name='后台标题')
shenfen = models.CharField(max_length=20, choices=SHENFEN_CHOICES, db_index=True, verbose_name='适用身份')
mode = models.PositiveSmallIntegerField(choices=MODE_CHOICES, default=MODE_TEXT, verbose_name='展示模式')
content_title = models.CharField(max_length=200, blank=True, default='', verbose_name='前端展示标题')
content_text = models.TextField(blank=True, default='', verbose_name='文字内容')
version = models.PositiveIntegerField(default=1, verbose_name='版本号')
is_active = models.BooleanField(default=True, verbose_name='是否启用')
must_sign = models.BooleanField(default=True, verbose_name='是否强制签署')
sort_order = models.IntegerField(default=0, verbose_name='排序')
created_at = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
updated_at = models.DateTimeField(auto_now=True, verbose_name='更新时间')
class Meta:
db_table = 'xcx_xieyi'
verbose_name = '小程序协议'
verbose_name_plural = verbose_name
ordering = ['sort_order', 'id']
def __str__(self):
return f'{self.title}({self.get_shenfen_display()})'
class XcxXieyiImage(models.Model):
"""协议图片(纯图片模式,支持多张)"""
xieyi = models.ForeignKey(XcxXieyi, on_delete=models.CASCADE, related_name='images', verbose_name='协议')
image_path = models.CharField(max_length=500, verbose_name='OSS相对路径')
sort_order = models.IntegerField(default=0, verbose_name='排序')
class Meta:
db_table = 'xcx_xieyi_image'
verbose_name = '协议图片'
verbose_name_plural = verbose_name
ordering = ['sort_order', 'id']
class XcxXieyiQianshu(models.Model):
"""用户协议签署记录"""
yonghuid = models.CharField(max_length=7, db_index=True, verbose_name='用户ID')
xieyi = models.ForeignKey(XcxXieyi, on_delete=models.CASCADE, related_name='sign_records', verbose_name='协议')
xieyi_version = models.PositiveIntegerField(verbose_name='签署时协议版本')
shenfen = models.CharField(max_length=20, verbose_name='签署时身份')
signature_path = models.CharField(max_length=500, verbose_name='签名图OSS路径')
signed_at = models.DateTimeField(auto_now_add=True, verbose_name='签署时间')
client_ip = models.CharField(max_length=64, blank=True, default='', verbose_name='客户端IP')
class Meta:
db_table = 'xcx_xieyi_qianshu'
verbose_name = '协议签署记录'
verbose_name_plural = verbose_name
indexes = [
models.Index(fields=['yonghuid', 'xieyi']),
]
class WechatPayMchConfig(models.Model):
"""
微信商家转账(自动提现收款)商户号配置。
收款发起按 priority 升序轮换;打款记录必须写入 mch_id回调/查单按记录反查。
"""
mch_id = models.CharField(max_length=32, unique=True, db_index=True, verbose_name='商户号')
name = models.CharField(max_length=100, blank=True, default='', verbose_name='备注名称')
appid = models.CharField(max_length=64, verbose_name='小程序AppID')
api_v3_key = models.CharField(max_length=64, verbose_name='APIv3密钥')
private_key_path = models.CharField(max_length=500, verbose_name='商户私钥pem路径')
cert_serial_no = models.CharField(max_length=128, verbose_name='商户证书序列号')
platform_pub_key_path = models.CharField(
max_length=500, blank=True, default='', verbose_name='微信平台公钥pem路径'
)
notify_url = models.CharField(max_length=500, blank=True, default='', verbose_name='转账回调URL')
transfer_scene_id = models.CharField(max_length=32, default='1005', verbose_name='转账场景ID')
priority = models.IntegerField(default=100, db_index=True, verbose_name='优先级(越小越优先)')
enabled = models.BooleanField(default=True, db_index=True, verbose_name='是否启用')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
class Meta:
db_table = 'wechat_pay_mch_config'
verbose_name = '微信转账商户配置'
verbose_name_plural = verbose_name
ordering = ['priority', 'id']
def __str__(self):
return f'{self.mch_id}({self.name or "-"})'
class UserWechatMchBind(models.Model):
"""
用户指定收款商户号:启用后该用户收款强制只用绑定商户,不参与自动轮换。
改绑不会改变已发出打款单的查单商户(仍按 TixianAutoRecord.mch_id
"""
yonghuid = models.CharField(max_length=32, unique=True, db_index=True, verbose_name='用户ID')
mch_id = models.CharField(max_length=32, db_index=True, verbose_name='绑定商户号')
enabled = models.BooleanField(default=True, db_index=True, verbose_name='是否启用')
remark = models.CharField(max_length=200, blank=True, default='', verbose_name='备注')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')
update_time = models.DateTimeField(auto_now=True, verbose_name='更新时间')
class Meta:
db_table = 'user_wechat_mch_bind'
verbose_name = '用户转账商户绑定'
verbose_name_plural = verbose_name
def __str__(self):
return f'{self.yonghuid}->{self.mch_id}'