"""商业交易模型 —— 与 xiaoxia-admin 共享表的 ORM 映射。 xiaoxia-admin(管理后台)与 xiaoxia-saas(用户端)共享同一个数据库: - plans / subscriptions 表由 admin 的 alembic 迁移创建(admin_alembic_version) - 用户端在支付链路中需要读取套餐、写入订阅,因此在此做最小映射 注意:不要在此给这些表建迁移;表结构变更走 xiaoxia-admin 仓库。 """ from __future__ import annotations from datetime import UTC, datetime from sqlalchemy import Boolean, Column, DateTime, Integer, Numeric, String, Text from sqlalchemy.orm import declarative_base CommerceBase: Any = declarative_base() def _now() -> datetime: return datetime.now(UTC) class PlanModel(CommerceBase): """admin 端 plans 套餐表(只读映射)。""" __tablename__ = "plans" id = Column(String(36), primary_key=True) level_id = Column(String(36), nullable=True) plan_key = Column(String(50), nullable=False) name = Column(String(100), nullable=False) description = Column(Text, nullable=True) monthly_price = Column(Numeric(10, 2), nullable=False, default=0) yearly_price = Column(Numeric(10, 2), nullable=False, default=0) is_enabled = Column(Boolean, nullable=False, default=True) display_order = Column(Integer, default=0) created_at = Column(DateTime, default=_now) class SubscriptionRecordModel(CommerceBase): """admin 端 subscriptions 订阅记录表(支付成功后写入)。""" __tablename__ = "subscriptions" id = Column(String(36), primary_key=True) user_id = Column(String(36), nullable=False, index=True) plan_id = Column(String(36), nullable=False, index=True) status = Column(String(20), nullable=False, default="active") billing_cycle = Column(String(10), nullable=False) start_date = Column(DateTime, nullable=False) end_date = Column(DateTime, nullable=False) cancelled_at = Column(DateTime, nullable=True) created_at = Column(DateTime, default=_now) updated_at = Column(DateTime, default=_now)