You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django模型中存储committee项目的用户月度缴费数据

解决方案

模型结构调整

你现有模型的核心问题是Participants表仅存储了整体缴费数据,无法区分月度缴费情况,需要新增月度缴费记录表单独存储每个用户每个月的缴费、中奖相关数据。
调整后的完整模型代码如下:

from django.db import models
from django.contrib.auth import get_user_model

Profile = get_user_model()

class Committee(models.Model):
    committee_creator = models.ForeignKey(Profile, on_delete=models.CASCADE)
    committee_name = models.CharField(max_length=100)
    committee_members_limit = models.IntegerField()
    committee_amount_per_month = models.IntegerField(default=0)
    committee_month_period = models.IntegerField(default=0)
    committee_amount_limit = models.IntegerField(null=True)
    committee_starting_date = models.DateTimeField(auto_now_add=False)
    committee_ending_date = models.DateTimeField(auto_now_add=False)

class Participant(models.Model):
    # 原模型名建议从Participants改成单数,符合Django命名规范
    user = models.ForeignKey(Profile, on_delete=models.CASCADE)
    committee = models.ForeignKey(Committee, on_delete=models.CASCADE, related_name="participants")

    class Meta:
        # 保证同一个用户不能重复加入同一个committee
        unique_together = ('user', 'committee')

    # 动态计算总已缴金额,不冗余存储避免数据不一致
    @property
    def total_paid_amount(self):
        return self.monthly_payments.filter(status=2).aggregate(total=models.Sum('paid_amount'))['total'] or 0

class MonthlyPaymentRecord(models.Model):
    PAYMENT_STATUS = [
        (0, '待支付'),
        (1, '已提交凭证待审核'),
        (2, '缴费已确认'),
        (3, '已逾期'),
    ]
    participant = models.ForeignKey(Participant, on_delete=models.CASCADE, related_name="monthly_payments")
    committee = models.ForeignKey(Committee, on_delete=models.CASCADE)
    # 缴费月份,统一存当月1号的日期即可,比如2024-05-01代表2024年5月的缴费
    payment_month = models.DateField()
    # 冗余存储当月应缴金额,避免后续committee修改月缴金额导致历史数据混乱
    payable_amount = models.IntegerField()
    paid_amount = models.IntegerField(default=0)
    status = models.SmallIntegerField(choices=PAYMENT_STATUS, default=0)
    payment_slip = models.ImageField(upload_to='payment_slips/', null=True, blank=True)
    paid_time = models.DateTimeField(null=True, blank=True)
    # 标记该用户是否为当月的资金获得者
    is_monthly_winner = models.BooleanField(default=False)

    class Meta:
        # 联合唯一约束:同一个用户在同一个committee的同一个月份仅能有一条缴费记录
        constraints = [
            models.UniqueConstraint(fields=['participant', 'committee', 'payment_month'], name='unique_monthly_payment')
        ]

核心逻辑实现说明

  • 月度缴费记录生成:可以配置Django定时任务,每月1号自动为所有处于有效期内的committee的所有参与者,生成当月的MonthlyPaymentRecord记录,初始状态设为待支付
  • 缴费状态展示:查询某个用户在某个committee下的待缴费项时,仅需过滤该用户关联的MonthlyPaymentRecord中状态不等于缴费已确认的记录即可
  • 月度中奖逻辑:每月开奖后,将对应中奖用户当月的MonthlyPaymentRecord的is_monthly_winner字段设为True即可快速查询历史中奖记录

优化建议

  • 无需在Participant表存储冗余的总缴费金额、整体缴费状态,全部通过关联的MonthlyPaymentRecord动态聚合计算,避免多数据源导致的数据不一致问题
  • 状态使用枚举配置替代布尔值,后续如果需要新增支付失败、退款等状态无需修改表结构

内容的提问来源于stack exchange,提问作者faiz khan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 15:21:01