# 数据库模型 - 使用字段编码 from sqlalchemy import Column, String, Float, Boolean, DateTime, Integer, Text, ForeignKey from sqlalchemy.orm import relationship from sqlalchemy.sql import func from app.core.database import Base import uuid def generate_uuid(): """生成 UUID 字符串""" return str(uuid.uuid4()) class User(Base): __tablename__ = "users" # f99 系统字段 f99_90_id = Column(String(36), primary_key=True, default=generate_uuid) f99_91_user_id = Column(String(36), unique=True, nullable=False, index=True) f01_01_name = Column(String(255), unique=True, nullable=False, index=True) # username email = Column(String(255), unique=True, nullable=True, index=True) phone = Column(String(50), nullable=True) avatar = Column(String(500), nullable=True) address = Column(String(500), nullable=True) bio = Column(Text, nullable=True) password = Column(String(255), nullable=False) role = Column(String(50), default="user") # last_login = Column(DateTime(timezone=True), nullable=True) f99_92_created_at = Column(DateTime(timezone=True), server_default=func.now()) f99_93_updated_at = Column(DateTime(timezone=True), onupdate=func.now()) collections = relationship("Collection", back_populates="user", cascade="all, delete-orphan") operations = relationship("Operation", back_populates="user", cascade="all, delete-orphan") custom_fields = relationship("CustomField", back_populates="user", cascade="all, delete-orphan") class Collection(Base): __tablename__ = "collections" # f99 系统字段 f99_90_id = Column(String(36), primary_key=True, default=generate_uuid) f99_91_user_id = Column(String(36), ForeignKey("users.f99_90_id", ondelete="CASCADE"), nullable=False, index=True) f99_92_created_at = Column(DateTime(timezone=True), server_default=func.now(), index=True) f99_93_updated_at = Column(DateTime(timezone=True), onupdate=func.now()) # f01 基本信息 f01_01_name = Column(String(255), nullable=False) f01_02_code = Column(String(50), nullable=True, index=True) f01_03_category = Column(String(100), nullable=False, index=True) f01_04_status = Column(String(50), default="in_collection", index=True) f01_05_remark = Column(Text, nullable=True) # f02 详细字段 f02_10_prefix_serial = Column(String(50), nullable=True, index=True) f02_11_version = Column(String(100), nullable=True, index=True) f02_12_packaging = Column(String(100), nullable=True, index=True) f02_13_rarity = Column(String(50), nullable=True, index=True) # 珍惜度 f02_14_number_category = Column(String(20), nullable=True, index=True) # 号码分类 # f03 评级信息 f03_20_is_graded = Column(Boolean, default=False, index=True) f03_21_grading_company = Column(String(100), nullable=True, index=True) f03_22_grading_score = Column(String(20), nullable=True, index=True) f03_23_three_star = Column(Boolean, default=False, index=True) # f04 特殊信息 f04_30_special_mark = Column(String(200), nullable=True, index=True) f04_31_serial_feature = Column(String(100), nullable=True, index=True) f04_32_issuer = Column(String(100), nullable=True, index=True) f04_33_issue_year = Column(String(20), nullable=True, index=True) f04_34_material = Column(String(50), nullable=True) f04_35_denomination = Column(String(20), nullable=True) f04_36_issue_quantity = Column(String(50), nullable=True) # f05 价格信息 f05_40_cost_price = Column(Float, nullable=True, index=True) f05_41_target_price = Column(Float, nullable=True, index=True) f05_42_goal_price = Column(Float, nullable=True) f05_43_repair_fee = Column(Float, nullable=True) f05_44_grading_fee = Column(Float, nullable=True) # f06 其他信息 f06_50_purpose = Column(String(100), nullable=True) user = relationship("User", back_populates="collections") images = relationship("CollectionImage", back_populates="collection", cascade="all, delete-orphan") operations = relationship("Operation", back_populates="collection", cascade="all, delete-orphan") class CollectionImage(Base): __tablename__ = "collection_images" id = Column(String(36), primary_key=True, default=generate_uuid) collection_id = Column(String(36), ForeignKey("collections.f99_90_id", ondelete="CASCADE"), nullable=False, index=True) filename = Column(String(255), nullable=False) original_name = Column(String(255), nullable=True) path = Column(String(500), nullable=True) created_at = Column(DateTime(timezone=True), server_default=func.now()) collection = relationship("Collection", back_populates="images") class Operation(Base): __tablename__ = "operations" f99_90_id = Column(String(36), primary_key=True, default=generate_uuid) f99_91_user_id = Column(String(36), ForeignKey("collections.f99_90_id", ondelete="CASCADE"), nullable=False, index=True) f99_92_user_id = Column(String(36), ForeignKey("users.f99_90_id", ondelete="CASCADE"), nullable=False, index=True) type = Column(String(50), nullable=False, index=True) price = Column(Float, nullable=True) note = Column(Text, nullable=True) f99_93_created_at = Column(DateTime(timezone=True), server_default=func.now(), index=True) collection = relationship("Collection", back_populates="operations") user = relationship("User", back_populates="operations") class CustomField(Base): __tablename__ = "custom_fields" id = Column(String(36), primary_key=True, default=generate_uuid) user_id = Column(String(36), ForeignKey("users.f99_90_id", ondelete="CASCADE"), nullable=False, index=True) name = Column(String(100), nullable=False) field_type = Column(String(50), default="text") options = Column(Text, nullable=True) required = Column(Boolean, default=False) visible = Column(Boolean, default=True) sort_order = Column(Integer, default=0) created_at = Column(DateTime(timezone=True), server_default=func.now()) user = relationship("User", back_populates="custom_fields")