""" 积分流水表 ========== 记录每一笔积分变动,用于审计和对账。 变动类型: - recharge:充值 - consume:消费(AI 调用) - expire:过期 - refund:返还(预扣后失败或实际少于预估) """ import uuid from sqlalchemy import BigInteger, String, Text from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.orm import Mapped, mapped_column from app.models.base import BaseModelBigInt class PointTransaction(BaseModelBigInt): """积分流水""" __tablename__ = "mjk_point_transactions" user_id: Mapped[uuid.UUID] = mapped_column( UUID(as_uuid=True), nullable=False, comment="用户 ID", ) type: Mapped[str] = mapped_column( String(20), nullable=False, comment="变动类型:recharge / consume / expire / refund", ) amount: Mapped[int] = mapped_column( default=0, nullable=False, comment="变动数量(正数)", ) balance_before: Mapped[int] = mapped_column( default=0, nullable=False, comment="变动前总余额", ) balance_after: Mapped[int] = mapped_column( default=0, nullable=False, comment="变动后总余额", ) source_type: Mapped[str | None] = mapped_column( String(32), nullable=True, comment="消费来源类型:script / polish / voice_clone / tts / video", ) source_id: Mapped[str | None] = mapped_column( String(64), nullable=True, comment="关联的任务 ID 或订单 ID", ) batch_id: Mapped[int | None] = mapped_column( BigInteger, nullable=True, comment="关联的积分批次 ID(消费时记录从哪个批次扣)", ) duration: Mapped[float | None] = mapped_column( nullable=True, comment="时长(秒),按秒计费业务记录", ) category: Mapped[str | None] = mapped_column( String(32), nullable=True, comment="业务分类:脚本生成 / 配音合成 / 视频生成 / 压制成片 / 字幕烧录 / 封面设计 / 充值", ) description: Mapped[str | None] = mapped_column( Text, nullable=True, comment="描述", )