b597d715c8
后端: - 修复 get_current_user 未校验 is_active,被封禁用户仍可用旧 Token - auth.py 捕获 ValueError 转 HTTPException(验证码错误、账号被封、Token 无效等不再返回 500) - 修正 SMS 每日上限注释(3次 → 10次) - 修复迁移脚本外键引用错误:users.id → mjk_users.id - 新建积分系统 4 张表的迁移(mjk_user_points/batches/transactions/recharge_orders) - pyproject.toml 补充 alembic + psycopg2-binary 依赖 - ruff 格式修复(import 排序等) 前端: - 修复 doRefreshToken 成功后不持久化新 Token 的严重 bug - 修复应用重启后 SSE 不自动重连(收不到踢人通知) - 修复 App.tsx handleLogout 未 await - client.ts 统一从 utils/env 导入 isTauri,默认 base URL 兜底 localhost:8000 - 清理 ~20 个未使用的 hooks/utils/api 模块/组件导出 - 修复所有 ESLint 警告(206 → 0)和 TSC 错误 - 测试通过(5/5) 其他: - 更新 requirements.lock 和 uv.lock
62 lines
1.5 KiB
Python
62 lines
1.5 KiB
Python
"""
|
|
积分批次表
|
|
==========
|
|
|
|
每笔充值产生一个批次,记录初始积分、剩余积分、过期时间。
|
|
|
|
消费时按过期时间升序扣减(FIFO,先充先用)。
|
|
"""
|
|
|
|
import uuid
|
|
from datetime import datetime
|
|
|
|
from sqlalchemy import DateTime, ForeignKey, String
|
|
from sqlalchemy.dialects.postgresql import UUID
|
|
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",
|
|
)
|