Auto generate engagement tasks after AQMM activation
This commit is contained in:
@@ -843,10 +843,36 @@ def get_or_create_engagement_closure(
|
||||
return row
|
||||
|
||||
|
||||
def _normal_tasks_completed(db: Session, *, subscription_id: int) -> bool:
|
||||
def _task_generation_counts(db: Session, *, subscription: ClientServiceSubscription) -> tuple[int, int]:
|
||||
"""Return (expected_active_templates, generated_active_tasks) for an engagement.
|
||||
|
||||
This is intentionally read-only and uses the same active firm task template scope as
|
||||
generate_tasks_for_subscription(). It lets closure readiness distinguish a genuinely
|
||||
completed engagement from an engagement where execution tasks were never generated.
|
||||
"""
|
||||
expected = db.execute(
|
||||
select(func.count(FirmServiceTaskTemplate.id)).where(
|
||||
FirmServiceTaskTemplate.tenant_id == subscription.tenant_id,
|
||||
FirmServiceTaskTemplate.service_catalogue_id == subscription.service_catalogue_id,
|
||||
FirmServiceTaskTemplate.is_active.is_(True),
|
||||
)
|
||||
).scalar_one()
|
||||
generated = db.execute(
|
||||
select(func.count(ClientServiceTaskInstance.id)).where(
|
||||
ClientServiceTaskInstance.subscription_id == subscription.id,
|
||||
ClientServiceTaskInstance.is_active.is_(True),
|
||||
)
|
||||
).scalar_one()
|
||||
return int(expected or 0), int(generated or 0)
|
||||
|
||||
|
||||
def _normal_tasks_completed(db: Session, *, subscription: ClientServiceSubscription) -> bool:
|
||||
expected_count, generated_count = _task_generation_counts(db, subscription=subscription)
|
||||
if expected_count > 0 and generated_count == 0:
|
||||
return False
|
||||
open_task = db.execute(
|
||||
select(ClientServiceTaskInstance.id).where(
|
||||
ClientServiceTaskInstance.subscription_id == subscription_id,
|
||||
ClientServiceTaskInstance.subscription_id == subscription.id,
|
||||
ClientServiceTaskInstance.is_active.is_(True),
|
||||
ClientServiceTaskInstance.status.notin_(list(CLOSED_TASK_STATUSES)),
|
||||
)
|
||||
@@ -891,11 +917,14 @@ def _udin_completed(db: Session, *, subscription_id: int) -> bool:
|
||||
def closure_readiness_for_subscription(db: Session, *, subscription: ClientServiceSubscription) -> dict:
|
||||
assurance = quality_required_for_engagement(subscription.engagement_type)
|
||||
aqmm_summary = aqmm_task_summary_for_subscription(db, subscription_id=subscription.id)
|
||||
normal_tasks_done = _normal_tasks_completed(db, subscription_id=subscription.id)
|
||||
expected_task_count, generated_task_count = _task_generation_counts(db, subscription=subscription)
|
||||
tasks_generated = expected_task_count == 0 or generated_task_count > 0
|
||||
normal_tasks_done = _normal_tasks_completed(db, subscription=subscription)
|
||||
|
||||
aqmm_acceptance_completed = (not assurance) or getattr(subscription, "quality_acceptance_status", None) == QUALITY_APPROVED
|
||||
aqmm_tasks_completed = (not assurance) or (
|
||||
aqmm_summary["mandatory_done"] == aqmm_summary["mandatory"]
|
||||
tasks_generated
|
||||
and aqmm_summary["mandatory_done"] == aqmm_summary["mandatory"]
|
||||
and aqmm_summary["evidence_missing"] == 0
|
||||
and aqmm_summary["manager_review_pending"] == 0
|
||||
and aqmm_summary["partner_review_pending"] == 0
|
||||
@@ -903,7 +932,8 @@ def closure_readiness_for_subscription(db: Session, *, subscription: ClientServi
|
||||
and aqmm_summary["rework_open"] == 0
|
||||
)
|
||||
evidence_review_completed = (not assurance) or (
|
||||
aqmm_summary["evidence_missing"] == 0
|
||||
tasks_generated
|
||||
and aqmm_summary["evidence_missing"] == 0
|
||||
and aqmm_summary["manager_review_pending"] == 0
|
||||
and aqmm_summary["partner_review_pending"] == 0
|
||||
and aqmm_summary["review_partner_review_pending"] == 0
|
||||
@@ -917,6 +947,9 @@ def closure_readiness_for_subscription(db: Session, *, subscription: ClientServi
|
||||
return {
|
||||
"assurance": assurance,
|
||||
"aqmm_task_summary": aqmm_summary,
|
||||
"expected_task_count": expected_task_count,
|
||||
"generated_task_count": generated_task_count,
|
||||
"tasks_generated": tasks_generated,
|
||||
"normal_tasks_completed": normal_tasks_done,
|
||||
"aqmm_acceptance_completed": aqmm_acceptance_completed,
|
||||
"aqmm_tasks_completed": aqmm_tasks_completed,
|
||||
@@ -943,7 +976,9 @@ def update_engagement_closure_from_sources(
|
||||
row.normal_tasks_completed = bool(summary["normal_tasks_completed"])
|
||||
|
||||
blockers: list[str] = []
|
||||
if not row.normal_tasks_completed:
|
||||
if not summary.get("tasks_generated", True):
|
||||
blockers.append("execution tasks not generated")
|
||||
elif not row.normal_tasks_completed:
|
||||
blockers.append("open work tracker tasks pending")
|
||||
if summary["assurance"]:
|
||||
if not row.aqmm_acceptance_completed:
|
||||
|
||||
Reference in New Issue
Block a user