from django.db import models from gvsdsdk.model_base import QModel from django.utils import timezone class Shangpin(QModel): """商品表 - 100-1000条数据""" id = models.AutoField(primary_key=True, verbose_name='商品ID') biaoqian = models.CharField(max_length=45,null=True, blank=True, verbose_name='商品标题') # 15汉字 jiage = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, verbose_name='商品价格') kucun = models.PositiveIntegerField(default=0, verbose_name='商品库存') leixing_id = models.PositiveIntegerField(null=True, blank=True,verbose_name='商品类型ID') # 直接存数字 zhuanqu_id = models.PositiveIntegerField(null=True, blank=True,verbose_name='商品专区ID') # 直接存数字 zhenshi_xiaoliang = models.PositiveIntegerField(default=0, verbose_name='商品真实销量') duiwai_xiaoliang = models.PositiveIntegerField(default=0, verbose_name='商品对外销量') jieshao = models.TextField(null=True, blank=True, verbose_name='商品介绍') # 新增字段 xiadan_xuzhi = models.TextField(null=True, blank=True, verbose_name='下单须知') # 支持500字,可换行 guize_tupian = models.CharField(max_length=500, null=True, blank=True, verbose_name='规则图片URL') yaoqiuleixing = models.PositiveIntegerField(null=True, blank=True, verbose_name='抢单要求类型') huiyuan_id = models.CharField(max_length=6, null=True, blank=True, verbose_name='会员ID') yongjin = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True,verbose_name='佣金要求') # 🔥 新增:是否开启打手额外分成 kaioi_ewai_dashou_fencheng = models.BooleanField(default=False, verbose_name='是否开启打手额外分成') # 🔥 新增:打手额外分成金额(开启时使用此值,否则按利率计算) ewai_dashou_fencheng = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True,verbose_name='打手额外分成金额') # 原有图片URL tupian_url = models.CharField(max_length=500, null=True, blank=True, verbose_name='商品图片URL') CreateTime = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') UpdateTime = models.DateTimeField(auto_now=True, verbose_name='更改时间') paixu = models.IntegerField(default=0, verbose_name='排序权重') shenhezhuangtai = models.IntegerField(default=1, verbose_name='审核状态', help_text='1=正常, 2=审核专用') dianpu = models.ForeignKey( 'shop.Dianpu', # 🔥 跨应用完整路径 on_delete=models.CASCADE, null=True, blank=True, db_index=True, verbose_name='所属店铺' ) dianpu_leixing = models.ForeignKey( 'shop.ShangpinLeixingDianpu', on_delete=models.SET_NULL, null=True, blank=True, db_index=True, verbose_name='店铺商品类型' ) shangjia_zhuangtai = models.BooleanField(default=True, verbose_name='是否上架') fengjin_zhuangtai = models.BooleanField(default=True, verbose_name='是否封禁') shenhe_zhuangtai = models.BooleanField(default=False, verbose_name='平台审核状态',help_text='True=审核通过,False=未审核') club_id = models.CharField( max_length=16, default='xq', db_index=True, verbose_name='所属俱乐部', help_text='公共商品按俱乐部隔离;历史数据默认星阙 xq', ) # 转盘购票商品标记:True 时走转盘支付,不走普通点单进抢池;默认 False,xq/xzj 不受影响 shi_zhuanpan = models.BooleanField( default=False, db_index=True, verbose_name='是否转盘购票商品', ) class Meta: db_table = 'shangpin' verbose_name = '商品' verbose_name_plural = '商品' # 不要索引!数据量太小 def __str__(self): return f"商品{self.id}:{self.biaoqian}" class ShangpinLeixing(QModel): """商品类型表 - <10条数据""" id = models.AutoField(primary_key=True, verbose_name='类型ID') yaoqiuleixing = models.PositiveIntegerField(null=True, blank=True, verbose_name='抢单要求类型') huiyuan_id = models.CharField(max_length=6, null=True, blank=True, verbose_name='会员ID') yongjin = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True, verbose_name='佣金要求') jieshao = models.CharField(max_length=45, null=True, blank=True, verbose_name='类型介绍') # 15汉字 tupian_url = models.CharField(max_length=500, null=True, blank=True, verbose_name='类型图片URL') # 用CharField paixu = models.IntegerField(default=0, verbose_name='排序权重') shenhezhuangtai = models.IntegerField(default=1, verbose_name='审核状态', help_text='1=正常, 2=审核专用') bankuai = models.ForeignKey( 'rank.Bankuai', on_delete=models.SET_NULL, null=True, blank=True, verbose_name='所属板块' ) class Meta: db_table = 'shangpin_leixing' verbose_name = '商品类型' verbose_name_plural = '商品类型' def __str__(self): return f"{self.jieshao}" class ShangpinZhuanqu(QModel): """商品专区表 - <50条数据""" id = models.AutoField(primary_key=True, verbose_name='专区ID') mingzi = models.CharField(max_length=45, null=True, blank=True, verbose_name='专区名称') # 15汉字 leixing_id = models.PositiveIntegerField(verbose_name='类型ID') # 直接存数字,不关联 paixu = models.IntegerField(default=0, verbose_name='排序权重') shenhezhuangtai = models.IntegerField(default=1, verbose_name='审核状态', help_text='1=正常, 2=审核专用') dianpu = models.ForeignKey( 'shop.Dianpu', # 🔥 跨应用完整路径 on_delete=models.CASCADE, null=True, blank=True, db_index=True, verbose_name='所属店铺' ) dianpu_leixing = models.ForeignKey( 'shop.ShangpinLeixingDianpu', on_delete=models.SET_NULL, null=True, blank=True, db_index=True, verbose_name='店铺商品类型' ) shangjia_zhuangtai = models.BooleanField(default=True, verbose_name='是否上架') fengjin_zhuangtai = models.BooleanField(default=True, verbose_name='是否封禁') club_id = models.CharField( max_length=16, default='xq', db_index=True, verbose_name='所属俱乐部', help_text='公共专区按俱乐部隔离;历史数据默认星阙 xq', ) # UFO 等点单端专区横滑图标(相对 OSS 路径或完整 URL);xq 可不填 tupian_url = models.CharField( max_length=500, null=True, blank=True, default='', verbose_name='专区图标URL', ) class Meta: db_table = 'shangpin_zhuanqu' verbose_name = '商品专区' verbose_name_plural = '商品专区' def __str__(self): return f"{self.mingzi}" class Huiyuan(QModel): huiyuan_id = models.CharField(max_length=6, unique=True, verbose_name='会员ID') jieshao = models.CharField(max_length=30, verbose_name='会员介绍') jtjieshao = models.TextField(null=True, blank=True, verbose_name='会员规则介绍') jiage = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, verbose_name='会员价格') guanshifc = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, verbose_name='管事分成') zuzhangfc = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, verbose_name='组长分成') goumai_cishu = models.PositiveIntegerField(default=0, verbose_name='购买次数') CreateTime = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') UpdateTime = models.DateTimeField(auto_now=True, verbose_name='更新时间') bankuai = models.ForeignKey( 'rank.Bankuai', on_delete=models.SET_NULL, null=True, blank=True, verbose_name='所属板块' ) is_bundle = models.BooleanField(default=False, verbose_name='是否为总会员(包含式)') class Meta: db_table = 'huiyuan' verbose_name = '会员' verbose_name_plural = '会员' def __str__(self): return f"会员{self.huiyuan_id}:{self.jieshao}" class Huiyuangoumai(QModel): id = models.AutoField(primary_key=True, verbose_name='购买记录ID') huiyuan_id = models.CharField(max_length=6, db_index=True, verbose_name='会员ID') yonghu_id = models.CharField(max_length=32, db_index=True, verbose_name='用户ID') huiyuan_zhuangtai = models.PositiveIntegerField(default=1, verbose_name='会员状态') jieshao = models.CharField(max_length=30,null=True,verbose_name='会员介绍') daoqi_time = models.DateTimeField(verbose_name='会员到期时间') CreateTime = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') UpdateTime = models.DateTimeField(auto_now=True, verbose_name='更新时间') club_id = models.CharField( max_length=16, default='xq', db_index=True, verbose_name='所属俱乐部', ) is_trial = models.BooleanField(default=False, verbose_name='当前是否为体验权益') has_used_trial = models.BooleanField(default=False, verbose_name='是否已购买过体验版') class Meta: db_table = 'huiyuangoumai' verbose_name = '用户购买会员' verbose_name_plural = '用户购买会员' # 添加这个联合唯一约束 unique_together = [['yonghu_id', 'huiyuan_id']] # 顺便优化索引(可选的,建议加) indexes = [ models.Index(fields=['yonghu_id']), models.Index(fields=['huiyuan_id']), models.Index(fields=['yonghu_id', 'huiyuan_id']), # 复合索引加速查询 ] def __str__(self): return f"用户{self.yonghu_id}-会员{self.huiyuan_id}" def jiance_shifou_daoqi(self): # 使用Django的timezone,它会自动处理时区 now = timezone.now() if now > self.daoqi_time: # 过期了 if self.huiyuan_zhuangtai != 0: self.huiyuan_zhuangtai = 0 self.save() return True else: # 没过期 if self.huiyuan_zhuangtai != 1: self.huiyuan_zhuangtai = 1 self.save() return False class Czjilu(QModel): dingdan_id = models.CharField(max_length=32, unique=True, db_index=True, verbose_name='订单ID') huiyuan_id = models.CharField(max_length=6, null=True, blank=True, verbose_name='会员ID') zhuangtai = models.IntegerField(null=True, blank=True, verbose_name='订单状态') yonghuid = models.CharField(max_length=7, db_index=True, verbose_name='用户ID') jine = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='订单金额') leixing = models.IntegerField( null=True, blank=True, verbose_name='充值类型,1:会员,2:押金,3:积分,4:商家充值,5:考核,6:罚款缴纳', ) shuoming = models.CharField(max_length=100, null=True, blank=True, verbose_name='订单说明') club_id = models.CharField( max_length=16, default='xq', db_index=True, verbose_name='所属俱乐部', ) is_trial = models.BooleanField(default=False, verbose_name='是否体验会员单') purchase_days = models.PositiveIntegerField( null=True, blank=True, verbose_name='下单锁定有效天数', ) CreateTime = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') UpdateTime = models.DateTimeField(auto_now=True, verbose_name='更新时间') class Meta: db_table = 'czjilu' verbose_name = '充值记录订单' verbose_name_plural = '充值记录订单' # 为高频查询字段添加索引 indexes = [ models.Index(fields=['dingdan_id']), models.Index(fields=['yonghuid']), ] class Gsfenhong(QModel): dingdan_id = models.CharField(max_length=32, unique=True, verbose_name='订单ID') guanshi = models.CharField(max_length=7, db_index=True, verbose_name='管事ID') dashouid = models.CharField(max_length=7, db_index=True,verbose_name='打手ID') shuoming = models.CharField(max_length=100, null=True, blank=True, verbose_name='订单说明') fenhong = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='订单分红金额') avatar = models.CharField(max_length=500, null=True, blank=True, verbose_name='打手头像') nicheng = models.CharField(max_length=50, null=True, verbose_name='打手昵称') CreateTime = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') UpdateTime = models.DateTimeField(auto_now=True, verbose_name='更新时间') zuzhang_id = models.CharField(max_length=7, null=True, blank=True, db_index=True, verbose_name='组长ID') zuzhang_fenhong = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True,verbose_name='组长分红金额') fenhong_leixing = models.PositiveSmallIntegerField( default=1, choices=[(1, '会员分红'), (2, '押金分红'), (3, '商家订单分红')], verbose_name='分红类型' ) huiyuan_id = models.CharField(max_length=6, null=True, blank=True, verbose_name='会员ID') club_id = models.CharField( max_length=16, default='xq', db_index=True, verbose_name='所属俱乐部', ) is_trial = models.BooleanField(default=False, verbose_name='是否体验会员分红') class Meta: db_table = 'gsfenhong' verbose_name = '管事分红记录' verbose_name_plural = '管事分红记录' # 为高频查询字段添加索引 indexes = [ models.Index(fields=['guanshi']), models.Index(fields=['dashouid']), ] class DuociFenhong(QModel): """ 多次分红配置表 用于配置不同次数下管事和组长的分红金额 """ huiyuan = models.CharField(max_length=10, verbose_name='会员ID') yonghuid = models.CharField(max_length=7, db_index=True, verbose_name='管事ID') club_id = models.CharField(max_length=16, default='xq', db_index=True, verbose_name='所属俱乐部') cishu = models.PositiveIntegerField(verbose_name='分红次数') guanshi_fenhong = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, verbose_name='管事分红金额') zuzhang_fenhong = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, verbose_name='组长分红金额') CreateTime = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') UpdateTime = models.DateTimeField(auto_now=True, verbose_name='更新时间') class Meta: db_table = 'duoci_fenhong' verbose_name = '多次分红配置' verbose_name_plural = '多次分红配置' unique_together = ('club_id', 'huiyuan', 'yonghuid', 'cishu') indexes = [ models.Index(fields=['yonghuid']), ] def __str__(self): return f"会员{self.huiyuan_id} 用户{self.yonghuid} 次数{self.cishu}" class ShangpinMeiriTongji(QModel): """ 商品每日统计表 按商品 + 日期维度记录点单、成交、退款及收益数据 日期精确到天,冗余年月日字段便于分组查询 """ shangpin = models.ForeignKey( 'products.Shangpin', on_delete=models.CASCADE, db_index=True, verbose_name='商品ID' ) riqi = models.DateField(db_index=True, verbose_name='统计日期') nian = models.PositiveSmallIntegerField(verbose_name='年份') yue = models.PositiveSmallIntegerField(verbose_name='月份') ri = models.PositiveSmallIntegerField(verbose_name='日') # 点单统计(下单即累加) diandan_zongliang = models.PositiveIntegerField(default=0, verbose_name='点单总量') diandan_zonge = models.DecimalField(max_digits=12, decimal_places=2, default=0.00, verbose_name='点单总额') # 成交统计(订单完成时累加) chengjiao_zongliang = models.PositiveIntegerField(default=0, verbose_name='成交总量') chengjiao_zonge = models.DecimalField(max_digits=12, decimal_places=2, default=0.00, verbose_name='成交总额') # 退款统计 tuikuan_zongliang = models.PositiveIntegerField(default=0, verbose_name='退款总量') tuikuan_zonge = models.DecimalField(max_digits=12, decimal_places=2, default=0.00, verbose_name='退款总额') # 收益统计(新增) pingtai_shouyi = models.DecimalField(max_digits=12, decimal_places=2, default=0.00, verbose_name='平台收益') dianpu_zongshouyi = models.DecimalField(max_digits=12, decimal_places=2, default=0.00, verbose_name='店铺总收益') CreateTime = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') UpdateTime = models.DateTimeField(auto_now=True, verbose_name='更新时间') class Meta: db_table = 'shangpin_meiri_tongji' verbose_name = '商品每日统计' verbose_name_plural = verbose_name # 每天每个商品唯一记录 unique_together = [['shangpin', 'riqi']] indexes = [ models.Index(fields=['shangpin', 'riqi']), models.Index(fields=['nian', 'yue', 'ri']), ] def __str__(self): return f"{self.shangpin.biaoqian} - {self.riqi}" def clean(self): """保存前自动填充年月日冗余字段""" if self.riqi: self.nian = self.riqi.year self.yue = self.riqi.month self.ri = self.riqi.day super().clean() def save(self, *args, **kwargs): self.clean() super().save(*args, **kwargs) # =========================================================================== # 转盘单(UFO 等俱乐部可选能力;未配置活动则接口无数据,不影响 xq/xzj) # =========================================================================== class ZhuanpanHuodong(QModel): """转盘活动:一个俱乐部可有多个;购票价格取关联商品 jiage。""" id = models.AutoField(primary_key=True) club_id = models.CharField(max_length=16, db_index=True, verbose_name='俱乐部') mingzi = models.CharField(max_length=64, default='幸运转盘', verbose_name='活动名') shangpin_id = models.PositiveIntegerField( db_index=True, verbose_name='购票商品ID', help_text='对应 Shangpin.id,且该商品建议 shi_zhuanpan=True', ) qiyong = models.BooleanField(default=True, db_index=True, verbose_name='是否启用') beizhu = models.CharField(max_length=200, blank=True, default='', verbose_name='备注') CreateTime = models.DateTimeField(auto_now_add=True) UpdateTime = models.DateTimeField(auto_now=True) class Meta: db_table = 'zhuanpan_huodong' verbose_name = '转盘活动' verbose_name_plural = verbose_name indexes = [models.Index(fields=['club_id', 'qiyong'])] class ZhuanpanJiangpin(QModel): """转盘奖品格:权重越高越易中;shi_xiexie=True 表示谢谢参与(不生成订单)。""" id = models.AutoField(primary_key=True) huodong_id = models.PositiveIntegerField(db_index=True, verbose_name='活动ID') mingzi = models.CharField(max_length=64, verbose_name='奖品名') tupian_url = models.CharField(max_length=500, blank=True, default='', verbose_name='奖品图') shangpin_id = models.PositiveIntegerField( null=True, blank=True, db_index=True, verbose_name='中奖后履约商品ID', ) quanzhong = models.PositiveIntegerField(default=1, verbose_name='中奖权重') paixu = models.PositiveSmallIntegerField(default=0, verbose_name='格子序号') shi_xiexie = models.BooleanField(default=False, verbose_name='是否谢谢参与') CreateTime = models.DateTimeField(auto_now_add=True) UpdateTime = models.DateTimeField(auto_now=True) class Meta: db_table = 'zhuanpan_jiangpin' verbose_name = '转盘奖品' verbose_name_plural = verbose_name indexes = [models.Index(fields=['huodong_id', 'paixu'])] class ZhuanpanJihui(QModel): """转盘抽奖机会单:支付成功后待抽,不进抢单池;抽中后再写 Order。 zhuangtai: 9=待支付 1=已付待抽 2=已抽 3=关闭/作废 """ id = models.AutoField(primary_key=True) club_id = models.CharField(max_length=16, db_index=True, verbose_name='俱乐部') yonghuid = models.CharField(max_length=32, db_index=True, verbose_name='用户UID') huodong_id = models.PositiveIntegerField(db_index=True, verbose_name='活动ID') czjilu_dingdan_id = models.CharField( max_length=64, unique=True, db_index=True, verbose_name='支付流水单号', ) jine = models.DecimalField(max_digits=10, decimal_places=2, default=0, verbose_name='购票金额') zhuangtai = models.PositiveSmallIntegerField(default=9, db_index=True, verbose_name='状态') nicheng = models.CharField(max_length=50, blank=True, default='', verbose_name='游戏昵称') beizhu = models.CharField(max_length=200, blank=True, default='', verbose_name='备注') zhongjiang_jiangpin_id = models.PositiveIntegerField(null=True, blank=True, verbose_name='中奖奖品ID') zhongjiang_shangpin_id = models.PositiveIntegerField(null=True, blank=True, verbose_name='中奖商品ID') dingdan_id = models.CharField( max_length=32, blank=True, default='', db_index=True, verbose_name='中奖后生成的订单号', ) CreateTime = models.DateTimeField(auto_now_add=True) UpdateTime = models.DateTimeField(auto_now=True) class Meta: db_table = 'zhuanpan_jihui' verbose_name = '转盘抽奖机会' verbose_name_plural = verbose_name indexes = [ models.Index(fields=['club_id', 'yonghuid', 'zhuangtai']), ]