""" Document Template and Version models """ from sqlalchemy import Column, Integer, String, Text, ForeignKey, Boolean, UniqueConstraint from sqlalchemy.orm import relationship from app.models.base import BaseModel class DocumentTemplate(BaseModel): """ High-level template metadata and current version pointer. """ __tablename__ = "document_templates" id = Column(Integer, primary_key=True, autoincrement=True, index=True) name = Column(String(200), unique=True, nullable=False, index=True) description = Column(Text) category = Column(String(100), index=True, default="GENERAL") active = Column(Boolean, default=True, nullable=False) # Creator username (optional) created_by = Column(String(150), ForeignKey("users.username"), nullable=True) # Pointer to the currently-approved version current_version_id = Column(Integer, ForeignKey("document_template_versions.id", use_alter=True), nullable=True) # Relationships current_version = relationship( "DocumentTemplateVersion", foreign_keys=[current_version_id], post_update=True, primaryjoin="DocumentTemplate.current_version_id==DocumentTemplateVersion.id", uselist=False, ) versions = relationship( "DocumentTemplateVersion", back_populates="template", cascade="all, delete-orphan", order_by="desc(DocumentTemplateVersion.created_at)", foreign_keys="DocumentTemplateVersion.template_id", ) keywords = relationship( "TemplateKeyword", back_populates="template", cascade="all, delete-orphan", order_by="asc(TemplateKeyword.keyword)", foreign_keys="TemplateKeyword.template_id", ) class DocumentTemplateVersion(BaseModel): """ Template binary version metadata and storage location """ __tablename__ = "document_template_versions" id = Column(Integer, primary_key=True, autoincrement=True, index=True) template_id = Column(Integer, ForeignKey("document_templates.id"), nullable=False, index=True) semantic_version = Column(String(50), nullable=False, index=True) # e.g., 1.0.0 storage_path = Column(String(512), nullable=False) # local path or S3 URI mime_type = Column(String(100), nullable=False) size = Column(Integer, nullable=False, default=0) checksum = Column(String(64), nullable=False) # sha256 hex changelog = Column(Text) created_by = Column(String(150), ForeignKey("users.username"), nullable=True) is_approved = Column(Boolean, default=True, nullable=False) # Relationships template = relationship( "DocumentTemplate", back_populates="versions", foreign_keys=[template_id], primaryjoin="DocumentTemplateVersion.template_id==DocumentTemplate.id", ) class TemplateKeyword(BaseModel): """ Keyword/tag assigned to a DocumentTemplate. """ __tablename__ = "template_keywords" id = Column(Integer, primary_key=True, autoincrement=True, index=True) template_id = Column(Integer, ForeignKey("document_templates.id"), nullable=False, index=True) keyword = Column(String(100), nullable=False, index=True) __table_args__ = ( UniqueConstraint("template_id", "keyword", name="uq_template_keyword"), ) template = relationship( "DocumentTemplate", back_populates="keywords", foreign_keys=[template_id], primaryjoin="TemplateKeyword.template_id==DocumentTemplate.id", )