Add task tool result bridge and evidence attachment workflow

This commit is contained in:
A R R R Associates
2026-08-31 15:24:09 +05:30
parent fbb8607842
commit a362cf438c
6 changed files with 497 additions and 6 deletions
+35 -1
View File
@@ -2,7 +2,7 @@ from __future__ import annotations
from datetime import date, datetime, timezone
from sqlalchemy import Boolean, Date, DateTime, ForeignKey, Integer, Numeric, String, Text, UniqueConstraint
from sqlalchemy import Boolean, Date, DateTime, ForeignKey, Integer, LargeBinary, Numeric, String, Text, UniqueConstraint
from sqlalchemy.orm import Mapped, mapped_column, relationship
from app.core.db.common import CommonBase
@@ -940,6 +940,40 @@ class ServiceTaskDocumentRequest(CommonBase):
verified_by = relationship("User", foreign_keys=[verified_by_user_id])
class ServiceTaskToolRun(CommonBase):
"""Persisted execution/result record for an ERP tool launched from a service task.
The result attachment is stored with the run so a tool can return its generated
workbook/PDF/JSON to the originating task without changing the existing document
module or historical EngagementDocument records.
"""
__tablename__ = "service_task_tool_runs"
id: Mapped[int] = mapped_column(Integer, primary_key=True, autoincrement=True)
tenant_id: Mapped[int] = mapped_column(ForeignKey("tenants.id", ondelete="CASCADE"), nullable=False, index=True)
task_instance_id: Mapped[int] = mapped_column(ForeignKey("client_service_task_instances.id", ondelete="CASCADE"), nullable=False, index=True)
client_id: Mapped[int] = mapped_column(ForeignKey("clients.id", ondelete="CASCADE"), nullable=False, index=True)
tool_code: Mapped[str] = mapped_column(String(80), nullable=False, index=True)
status: Mapped[str] = mapped_column(String(30), nullable=False, default="started", index=True)
summary: Mapped[str | None] = mapped_column(Text, nullable=True)
result_json: Mapped[str | None] = mapped_column(Text, nullable=True)
exception_count: Mapped[int | None] = mapped_column(Integer, nullable=True)
clean_pass: Mapped[bool | None] = mapped_column(Boolean, nullable=True)
output_filename: Mapped[str | None] = mapped_column(String(255), nullable=True)
output_content_type: Mapped[str | None] = mapped_column(String(120), nullable=True)
output_bytes: Mapped[bytes | None] = mapped_column(LargeBinary, nullable=True)
started_by_user_id: Mapped[int | None] = mapped_column(ForeignKey("users.id", ondelete="SET NULL"), nullable=True, index=True)
completed_by_user_id: Mapped[int | None] = mapped_column(ForeignKey("users.id", ondelete="SET NULL"), nullable=True, index=True)
started_at_utc: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False)
completed_at_utc: Mapped[datetime | None] = mapped_column(DateTime(timezone=True), nullable=True)
created_at_utc: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), nullable=False)
updated_at_utc: Mapped[datetime] = mapped_column(DateTime(timezone=True), default=lambda: datetime.now(timezone.utc), onupdate=lambda: datetime.now(timezone.utc), nullable=False)
task = relationship("ClientServiceTaskInstance", foreign_keys=[task_instance_id])
class ServiceTaskComment(CommonBase):
"""Communication timeline entry linked to a service task instance."""