111 lines
4.7 KiB
Python
111 lines
4.7 KiB
Python
from __future__ import annotations
|
|
|
|
from datetime import datetime
|
|
from typing import Any
|
|
|
|
from sqlalchemy import (
|
|
Boolean,
|
|
CheckConstraint,
|
|
DateTime,
|
|
Float,
|
|
Index,
|
|
Integer,
|
|
String,
|
|
Text,
|
|
UniqueConstraint,
|
|
func,
|
|
)
|
|
from sqlalchemy.orm import Mapped, mapped_column
|
|
from sqlalchemy.types import JSON
|
|
|
|
from app.db.base_class import Base
|
|
|
|
|
|
class AttachmentAssociationJob(Base):
|
|
"""可跨进程恢复的票据归集任务状态。"""
|
|
|
|
__tablename__ = "attachment_association_jobs"
|
|
__table_args__ = (
|
|
UniqueConstraint(
|
|
"tenant_id",
|
|
"owner_username",
|
|
"dedupe_key",
|
|
"generation",
|
|
name="uq_attachment_association_jobs_owner_dedupe",
|
|
),
|
|
CheckConstraint(
|
|
"status IN ('queued', 'running', 'succeeded', 'failed')",
|
|
name="ck_attachment_association_jobs_status",
|
|
),
|
|
CheckConstraint(
|
|
"attempt_count >= 0",
|
|
name="ck_attachment_association_jobs_attempt_count",
|
|
),
|
|
CheckConstraint(
|
|
"generation >= 1",
|
|
name="ck_attachment_association_jobs_generation",
|
|
),
|
|
CheckConstraint(
|
|
"status != 'running' OR lease_expires_at IS NOT NULL",
|
|
name="ck_attachment_association_jobs_running_lease",
|
|
),
|
|
Index(
|
|
"ix_attachment_association_jobs_owner_time",
|
|
"tenant_id",
|
|
"owner_username",
|
|
"created_at",
|
|
),
|
|
Index(
|
|
"ix_attachment_association_jobs_status_lease",
|
|
"status",
|
|
"lease_expires_at",
|
|
),
|
|
)
|
|
|
|
id: Mapped[str] = mapped_column(String(80), primary_key=True)
|
|
tenant_id: Mapped[str] = mapped_column(String(64), nullable=False)
|
|
owner_username: Mapped[str] = mapped_column(String(255), nullable=False)
|
|
owner_name: Mapped[str] = mapped_column(String(255), nullable=False, default="")
|
|
owner_context_json: Mapped[dict[str, Any]] = mapped_column(JSON, nullable=False, default=dict)
|
|
dedupe_key: Mapped[str] = mapped_column(String(64), nullable=False)
|
|
generation: Mapped[int] = mapped_column(Integer, nullable=False, default=1)
|
|
receipt_ids_json: Mapped[list[str]] = mapped_column(JSON, nullable=False, default=list)
|
|
prompt: Mapped[str] = mapped_column(Text, nullable=False, default="")
|
|
conversation_id: Mapped[str] = mapped_column(String(120), nullable=False, default="")
|
|
status: Mapped[str] = mapped_column(String(20), nullable=False, default="queued")
|
|
message: Mapped[str] = mapped_column(Text, nullable=False, default="")
|
|
claim_id: Mapped[str] = mapped_column(String(36), nullable=False, default="")
|
|
claim_no: Mapped[str] = mapped_column(String(80), nullable=False, default="")
|
|
uploaded_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
|
|
skipped_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
|
|
resolution: Mapped[str] = mapped_column(String(40), nullable=False, default="pending")
|
|
requires_confirmation: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
|
|
expense_case_id: Mapped[str] = mapped_column(String(36), nullable=False, default="")
|
|
application_claim_id: Mapped[str] = mapped_column(String(36), nullable=False, default="")
|
|
application_claim_no: Mapped[str] = mapped_column(String(80), nullable=False, default="")
|
|
confidence: Mapped[str] = mapped_column(String(20), nullable=False, default="")
|
|
confidence_score: Mapped[float] = mapped_column(Float, nullable=False, default=0.0)
|
|
match_reasons_json: Mapped[list[str]] = mapped_column(JSON, nullable=False, default=list)
|
|
exceptions_json: Mapped[list[str]] = mapped_column(JSON, nullable=False, default=list)
|
|
missing_fields_json: Mapped[list[str]] = mapped_column(JSON, nullable=False, default=list)
|
|
risk_items_json: Mapped[list[str]] = mapped_column(JSON, nullable=False, default=list)
|
|
candidates_json: Mapped[list[dict[str, Any]]] = mapped_column(JSON, nullable=False, default=list)
|
|
draft_payload_json: Mapped[dict[str, Any] | None] = mapped_column(JSON, nullable=True)
|
|
error: Mapped[str] = mapped_column(Text, nullable=False, default="")
|
|
attempt_count: Mapped[int] = mapped_column(Integer, nullable=False, default=0)
|
|
lease_expires_at: Mapped[datetime | None] = mapped_column(
|
|
DateTime(timezone=True),
|
|
nullable=True,
|
|
)
|
|
created_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True),
|
|
server_default=func.now(),
|
|
nullable=False,
|
|
)
|
|
updated_at: Mapped[datetime] = mapped_column(
|
|
DateTime(timezone=True),
|
|
server_default=func.now(),
|
|
onupdate=func.now(),
|
|
nullable=False,
|
|
)
|