51521fc0dd
- 微信支付从 APIv3 降级为 APIv2(MD5/XML) - 积分系统:充值下单、微信回调、消费冻结/结算/退款 - SMS B2M 短信验证码服务 - 双 Token 认证(Access 30min + Refresh 30days) - SSE 单设备踢人 - 用户设备管理、积分账户模型 - Alembic 迁移脚本
62 lines
1.5 KiB
Python
62 lines
1.5 KiB
Python
"""
|
|
积分批次表
|
|
==========
|
|
|
|
每笔充值产生一个批次,记录初始积分、剩余积分、过期时间。
|
|
|
|
消费时按过期时间升序扣减(FIFO,先充先用)。
|
|
"""
|
|
|
|
from datetime import UTC, datetime
|
|
|
|
import uuid
|
|
from sqlalchemy.dialects.postgresql import UUID
|
|
from sqlalchemy import DateTime, ForeignKey, String
|
|
from sqlalchemy.orm import Mapped, mapped_column
|
|
|
|
from app.models.base import BaseModelBigInt
|
|
|
|
|
|
class PointBatch(BaseModelBigInt):
|
|
"""积分批次"""
|
|
|
|
__tablename__ = "mjk_point_batches"
|
|
|
|
user_id: Mapped[uuid.UUID] = mapped_column(
|
|
UUID(as_uuid=True),
|
|
ForeignKey("mjk_users.id", ondelete="CASCADE"),
|
|
nullable=False,
|
|
comment="用户 ID",
|
|
)
|
|
|
|
amount: Mapped[int] = mapped_column(
|
|
default=0,
|
|
nullable=False,
|
|
comment="初始积分",
|
|
)
|
|
|
|
remaining: Mapped[int] = mapped_column(
|
|
default=0,
|
|
nullable=False,
|
|
comment="剩余可用积分(扣除冻结后)",
|
|
)
|
|
|
|
frozen: Mapped[int] = mapped_column(
|
|
default=0,
|
|
nullable=False,
|
|
comment="已冻结积分(预扣未结算)",
|
|
)
|
|
|
|
expired_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True),
|
|
nullable=False,
|
|
comment="过期时间(created_at + 180 天)",
|
|
)
|
|
|
|
source: Mapped[str] = mapped_column(
|
|
String(32),
|
|
default="wxpay",
|
|
nullable=False,
|
|
comment="来源:wxpay / invite / gift / compensation",
|
|
)
|