"""排行榜奖励 — 按俱乐部分奖,与集团展示榜分离。""" from django.db import models from gvsdsdk.model_base import QModel class RankRewardScheme(QModel): """俱乐部 + 身份 + 周期 奖励方案""" PERIOD_DAY = 'day' PERIOD_WEEK = 'week' PERIOD_MONTH = 'month' PERIOD_CHOICES = [ (PERIOD_DAY, '日榜(昨日)'), (PERIOD_WEEK, '周榜(上周)'), (PERIOD_MONTH, '月榜(上月)'), ] club_id = models.CharField(max_length=16, db_index=True, verbose_name='俱乐部ID') shenfen = models.CharField(max_length=16, db_index=True, verbose_name='身份') period_type = models.CharField(max_length=16, choices=PERIOD_CHOICES, verbose_name='周期类型') sort_field = models.CharField(max_length=32, verbose_name='排序指标键') title = models.CharField(max_length=128, blank=True, default='', verbose_name='展示标题') description = models.TextField(blank=True, default='', verbose_name='规则说明') enabled = models.BooleanField(default=False, verbose_name='启用') claim_days = models.PositiveSmallIntegerField(default=30, verbose_name='领取有效天数') activity_start = models.DateField(null=True, blank=True, verbose_name='活动开始日期') activity_end = models.DateField(null=True, blank=True, verbose_name='活动结束日期') min_metric = models.DecimalField( max_digits=12, decimal_places=2, default=0, verbose_name='最低指标门槛', ) CreateTime = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') UpdateTime = models.DateTimeField(auto_now=True, verbose_name='更新时间') class Meta: db_table = 'rank_reward_scheme' verbose_name = '排行榜奖励方案' verbose_name_plural = verbose_name unique_together = [['club_id', 'shenfen', 'period_type']] def __str__(self): return f'{self.club_id}:{self.shenfen}:{self.period_type}' class RankRewardTier(QModel): scheme = models.ForeignKey( RankRewardScheme, on_delete=models.CASCADE, related_name='tiers', verbose_name='方案', ) rank_from = models.PositiveSmallIntegerField(verbose_name='名次起') rank_to = models.PositiveSmallIntegerField(verbose_name='名次止') reward_amount = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='奖金(元)') label = models.CharField(max_length=32, blank=True, default='', verbose_name='档位标签') class Meta: db_table = 'rank_reward_tier' verbose_name = '排行榜奖励档位' verbose_name_plural = verbose_name ordering = ['rank_from'] def __str__(self): return f'{self.rank_from}-{self.rank_to} ¥{self.reward_amount}' class RankRewardSettlement(QModel): """结算批次 — 同一 club+方案+period_key 仅一条""" scheme = models.ForeignKey(RankRewardScheme, on_delete=models.CASCADE, verbose_name='方案') club_id = models.CharField(max_length=16, db_index=True, verbose_name='俱乐部ID') period_key = models.CharField(max_length=32, db_index=True, verbose_name='周期键') period_start = models.DateField(verbose_name='统计起始') period_end = models.DateField(verbose_name='统计截止') riqi_label = models.CharField(max_length=16, verbose_name='前端周期文案') sort_field = models.CharField(max_length=32, verbose_name='结算时排序字段快照') settled_at = models.DateTimeField(auto_now_add=True, verbose_name='结算时间') claim_count = models.PositiveIntegerField(default=0, verbose_name='生成待领取数') class Meta: db_table = 'rank_reward_settlement' verbose_name = '排行榜奖励结算' verbose_name_plural = verbose_name unique_together = [['club_id', 'scheme', 'period_key']] class RankRewardClaim(QModel): STATUS_PENDING = 0 STATUS_CLAIMED = 1 STATUS_EXPIRED = 2 STATUS_CANCELLED = 3 STATUS_CHOICES = [ (STATUS_PENDING, '待领取'), (STATUS_CLAIMED, '已领取'), (STATUS_EXPIRED, '已过期'), (STATUS_CANCELLED, '已取消'), ] settlement = models.ForeignKey( RankRewardSettlement, on_delete=models.CASCADE, related_name='claims', verbose_name='结算批次', ) club_id = models.CharField(max_length=16, db_index=True, verbose_name='俱乐部ID') yonghuid = models.CharField(max_length=7, db_index=True, verbose_name='用户ID') shenfen = models.CharField(max_length=16, verbose_name='身份') mingci = models.PositiveSmallIntegerField(verbose_name='名次') metric_value = models.DecimalField(max_digits=12, decimal_places=2, default=0, verbose_name='指标快照') reward_amount = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='奖金') status = models.PositiveSmallIntegerField(default=STATUS_PENDING, choices=STATUS_CHOICES, db_index=True) expire_at = models.DateTimeField(verbose_name='领取截止') claimed_at = models.DateTimeField(null=True, blank=True, verbose_name='领取时间') balance_field = models.CharField(max_length=32, verbose_name='入账字段') idempotent_key = models.CharField(max_length=96, unique=True, verbose_name='幂等键') CreateTime = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') UpdateTime = models.DateTimeField(auto_now=True, verbose_name='更新时间') class Meta: db_table = 'rank_reward_claim' verbose_name = '排行榜奖励领取' verbose_name_plural = verbose_name indexes = [ models.Index(fields=['yonghuid', 'status']), models.Index(fields=['club_id', 'status']), ] class RankRewardClaimLog(QModel): """领取审计 — 先记日志再入账""" ACTION_START = 'claim_start' ACTION_SUCCESS = 'claim_success' ACTION_REJECT = 'claim_reject' ACTION_CHOICES = [ (ACTION_START, '开始领取'), (ACTION_SUCCESS, '领取成功'), (ACTION_REJECT, '领取拒绝'), ] claim = models.ForeignKey( RankRewardClaim, on_delete=models.CASCADE, related_name='logs', verbose_name='领取记录', ) yonghuid = models.CharField(max_length=7, db_index=True, verbose_name='用户ID') action = models.CharField(max_length=32, choices=ACTION_CHOICES, verbose_name='动作') amount = models.DecimalField(max_digits=10, decimal_places=2, default=0, verbose_name='金额') detail = models.CharField(max_length=256, blank=True, default='', verbose_name='说明') CreateTime = models.DateTimeField(auto_now_add=True, verbose_name='创建时间') class Meta: db_table = 'rank_reward_claim_log' verbose_name = '排行榜奖励领取日志' verbose_name_plural = verbose_name ordering = ['-CreateTime']