From a512aec512de8d3c75850f353d75acbc8044f421 Mon Sep 17 00:00:00 2001 From: A R R R Associates Date: Fri, 7 Aug 2026 15:33:49 +0530 Subject: [PATCH] Align engagement task model and repair missing task generation --- app/modules/services/models.py | 17 ++++++++++++++++- scripts/repair_missing_engagement_tasks.py | 5 +++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/app/modules/services/models.py b/app/modules/services/models.py index 553147e..e95d4e4 100644 --- a/app/modules/services/models.py +++ b/app/modules/services/models.py @@ -2,7 +2,7 @@ from __future__ import annotations from datetime import date, datetime, timezone -from sqlalchemy import Boolean, Date, DateTime, ForeignKey, Integer, String, Text, UniqueConstraint +from sqlalchemy import Boolean, Date, DateTime, ForeignKey, Integer, Numeric, String, Text, UniqueConstraint from sqlalchemy.orm import Mapped, mapped_column, relationship from app.core.db.common import CommonBase @@ -743,6 +743,21 @@ class ClientServiceTaskInstance(CommonBase): status: Mapped[str] = mapped_column(String(30), nullable=False, default="pending", index=True) priority: Mapped[str] = mapped_column(String(20), nullable=False, default="normal") + # Structured checklist snapshot fields. These columns already exist in the + # production database via Alembic revision 20260719_task_checklist_fields. + # Keeping them on the ORM model is required so task generation and the + # existing Work Tracker checklist UI use the same persisted schema. + task_category: Mapped[str | None] = mapped_column(String(100), nullable=True, index=True) + response_required: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False) + response_type: Mapped[str] = mapped_column(String(20), nullable=False, default="NONE") + evidence_required: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False) + remarks_required_if_no: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False) + checklist_response: Mapped[str | None] = mapped_column(String(10), nullable=True) + checklist_text_response: Mapped[str | None] = mapped_column(Text, nullable=True) + checklist_number_response: Mapped[float | None] = mapped_column(Numeric(18, 2), nullable=True) + checklist_date_response: Mapped[date | None] = mapped_column(Date, nullable=True) + checklist_remarks: Mapped[str | None] = mapped_column(Text, nullable=True) + # Copied from FirmServiceTaskTemplate at generation time. Existing task # completion/evidence upload flow is reused to calculate AQMM quality status. is_aqmm_task: Mapped[bool] = mapped_column(Boolean, default=False, nullable=False, index=True) diff --git a/scripts/repair_missing_engagement_tasks.py b/scripts/repair_missing_engagement_tasks.py index 2b1b42c..7a91ef9 100644 --- a/scripts/repair_missing_engagement_tasks.py +++ b/scripts/repair_missing_engagement_tasks.py @@ -5,6 +5,11 @@ from collections import Counter from sqlalchemy import func, select +# Standalone utilities do not pass through FastAPI startup automatically. +# Importing startup loads the complete SQLAlchemy model registry (including +# ConsultantProfile and all relationship targets) before ORM queries compile. +import app.core.startup # noqa: F401 + from app.core.db.common import CommonSessionLocal from app.modules.services.execution import generate_tasks_for_subscription_if_ready from app.modules.services.models import (