from __future__ import annotations from datetime import datetime from typing import Any from sqlalchemy import DateTime, ForeignKey, Index, JSON, String, Text, UniqueConstraint from sqlalchemy.orm import Mapped, mapped_column, relationship from iti.db import Base, IdMixin, TimestampMixin class ExchangeTemplateModel(Base, IdMixin, TimestampMixin): __tablename__ = "exchange_templates" __table_args__ = ( UniqueConstraint( "biz_domain", "biz_obj", "operation", "code", name="uq_exchange_templates_scope_code", ), Index( "ix_exchange_templates_scope", "biz_domain", "biz_obj", "operation", ), ) code: Mapped[str] = mapped_column(String(128), unique=True, index=True, comment="模板编码") name: Mapped[str] = mapped_column(String(255), comment="模板名称") biz_domain: Mapped[str] = mapped_column(String(128), index=True, comment="业务域") biz_obj: Mapped[str] = mapped_column(String(128), index=True, comment="业务对象") operation: Mapped[str] = mapped_column(String(32), index=True, comment="业务操作") status: Mapped[str] = mapped_column(String(32), default="draft", index=True, comment="状态") description: Mapped[str | None] = mapped_column(Text, nullable=True, comment="说明") current_version: Mapped[str | None] = mapped_column( String(64), nullable=True, index=True, comment="当前版本" ) layout: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, comment="布局标记") meta: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, comment="扩展配置") versions: Mapped[list["ExchangeTemplateVersionModel"]] = relationship( back_populates="template", cascade="all, delete-orphan", ) class ExchangeTemplateVersionModel(Base, IdMixin, TimestampMixin): __tablename__ = "exchange_template_versions" __table_args__ = ( UniqueConstraint("template_id", "version", name="uq_exchange_template_versions_template_version"), Index("ix_exchange_template_versions_template_id_version", "template_id", "version"), ) template_id: Mapped[str] = mapped_column( String(36), ForeignKey("exchange_templates.id", ondelete="CASCADE"), index=True, comment="模板ID", ) version: Mapped[str] = mapped_column(String(64), comment="版本号") biz_domain: Mapped[str] = mapped_column(String(128), index=True, comment="业务域") biz_obj: Mapped[str] = mapped_column(String(128), index=True, comment="业务对象") operation: Mapped[str] = mapped_column(String(32), index=True, comment="业务操作") published_at: Mapped[datetime | None] = mapped_column( DateTime, nullable=True, comment="发布时间", ) file_key: Mapped[str | None] = mapped_column(String(512), nullable=True, comment="模板文件") checksum: Mapped[str | None] = mapped_column(String(128), nullable=True, comment="校验值") layout: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, comment="布局标记") variables: Mapped[list[dict[str, Any]]] = mapped_column(JSON, default=list, comment="模板变量") meta: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, comment="扩展配置") template: Mapped["ExchangeTemplateModel"] = relationship(back_populates="versions") class ExchangeTaskModel(Base, IdMixin, TimestampMixin): __tablename__ = "exchange_tasks" __table_args__ = ( Index( "ix_exchange_tasks_scope_status", "biz_domain", "biz_obj", "operation", "status", ), Index("ix_exchange_tasks_template_id_status", "template_id", "status"), Index("ix_exchange_tasks_version_id", "template_version_id"), ) template_id: Mapped[str | None] = mapped_column( String(36), ForeignKey("exchange_templates.id", ondelete="SET NULL"), nullable=True, index=True, comment="模板ID", ) template_version_id: Mapped[str | None] = mapped_column( String(36), ForeignKey("exchange_template_versions.id", ondelete="SET NULL"), nullable=True, index=True, comment="模板版本ID", ) biz_domain: Mapped[str] = mapped_column(String(128), index=True, comment="业务域") biz_obj: Mapped[str] = mapped_column(String(128), index=True, comment="业务对象") operation: Mapped[str] = mapped_column(String(32), index=True, comment="业务操作") status: Mapped[str] = mapped_column(String(32), default="pending", index=True, comment="状态") requested_by: Mapped[str | None] = mapped_column(String(36), nullable=True, index=True, comment="发起人") storage_key: Mapped[str | None] = mapped_column(String(512), nullable=True, comment="任务文件") checksum: Mapped[str | None] = mapped_column(String(128), nullable=True, comment="校验值") error_count: Mapped[int] = mapped_column(default=0, comment="错误数") success_count: Mapped[int] = mapped_column(default=0, comment="成功数") failed_count: Mapped[int] = mapped_column(default=0, comment="失败数") message: Mapped[str | None] = mapped_column(Text, nullable=True, comment="消息") input_payload: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, comment="输入参数") result_payload: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, comment="输出结果") started_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True, comment="开始时间") finished_at: Mapped[datetime | None] = mapped_column(DateTime, nullable=True, comment="结束时间") meta: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, comment="扩展配置") template: Mapped["ExchangeTemplateModel"] = relationship( foreign_keys=[template_id] ) version: Mapped["ExchangeTemplateVersionModel"] = relationship( foreign_keys=[template_version_id] ) rows: Mapped[list["ExchangeTaskRowModel"]] = relationship( back_populates="task", cascade="all, delete-orphan", ) class ExchangeTaskRowModel(Base, IdMixin, TimestampMixin): __tablename__ = "exchange_task_rows" __table_args__ = ( UniqueConstraint("task_id", "row_index", name="uq_exchange_task_rows_task_row"), Index("ix_exchange_task_rows_task_id_status", "task_id", "status"), ) task_id: Mapped[str] = mapped_column( String(36), ForeignKey("exchange_tasks.id", ondelete="CASCADE"), index=True, comment="任务ID", ) row_index: Mapped[int] = mapped_column(comment="行号") status: Mapped[str] = mapped_column(String(32), default="pending", index=True, comment="状态") data: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, comment="原始数据") message: Mapped[str | None] = mapped_column(Text, nullable=True, comment="错误信息") result: Mapped[dict[str, Any]] = mapped_column(JSON, default=dict, comment="结果数据") task: Mapped["ExchangeTaskModel"] = relationship(back_populates="rows")