862 lines
37 KiB
Python
862 lines
37 KiB
Python
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):
|
||
"""合作俱乐部/平台信息表"""
|
||
# 自己的俱乐部ID(6位字符)
|
||
club_id = models.CharField(max_length=6, db_index=True, verbose_name='本俱乐部ID')
|
||
# 对方的俱乐部ID(6位字符)
|
||
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密钥等
|
||
"""
|
||
# 俱乐部ID(6位字符,与 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='退款密钥路径')
|
||
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='商家派单最高金额(元)',
|
||
)
|
||
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}' |