Auto-sync system default tasks to firms and open engagements

This commit is contained in:
A R R R Associates
2026-09-19 12:47:53 +05:30
parent f6776cc96a
commit 2d6043962b
9 changed files with 857 additions and 313 deletions
+45 -6
View File
@@ -442,16 +442,18 @@ def sync_open_engagement_tasks_for_service(
catalogue_id: int,
user_id: int,
include_started_open_tasks: bool = False,
safe_system_rollout: bool = False,
) -> dict[str, int]:
templates = db.execute(
all_templates = db.execute(
select(FirmServiceTaskTemplate)
.where(
FirmServiceTaskTemplate.tenant_id == tenant_id,
FirmServiceTaskTemplate.service_catalogue_id == catalogue_id,
FirmServiceTaskTemplate.is_active.is_(True),
)
.order_by(FirmServiceTaskTemplate.sequence_no.asc(), FirmServiceTaskTemplate.id.asc())
).scalars().all()
templates = [row for row in all_templates if bool(row.is_active)]
inactive_templates = [row for row in all_templates if not bool(row.is_active)]
engagements = db.execute(
select(ClientServiceSubscription)
@@ -470,10 +472,21 @@ def sync_open_engagement_tasks_for_service(
"created": 0,
"updated_pending": 0,
"updated_started": 0,
"deactivated_pending": 0,
"preserved_history": 0,
}
for subscription in engagements:
if (
safe_system_rollout
and quality_required_for_engagement(subscription.engagement_type)
and getattr(subscription, "quality_acceptance_status", None) != QUALITY_APPROVED
):
# Preserve the existing assurance acceptance gate during automatic
# system-default rollout. Tasks will be generated by the normal flow
# once quality acceptance is approved.
continue
existing = db.execute(
select(ClientServiceTaskInstance).where(
ClientServiceTaskInstance.subscription_id == subscription.id,
@@ -549,6 +562,7 @@ def sync_open_engagement_tasks_for_service(
and task.completed_at_utc is None
and task.submitted_for_review_at_utc is None
and (task.rework_status or "none") == "none"
and not bool(getattr(task, "is_locked", False))
)
if never_started:
@@ -558,6 +572,8 @@ def sync_open_engagement_tasks_for_service(
subscription=subscription,
update_assignment=True,
)
if safe_system_rollout:
task.is_active = True
task.updated_by_user_id = user_id
result["updated_pending"] += 1
elif include_started_open_tasks and status in {"in_progress", "blocked"} and task.completed_at_utc is None:
@@ -571,12 +587,35 @@ def sync_open_engagement_tasks_for_service(
task.updated_by_user_id = user_id
result["updated_started"] += 1
else:
# Preserve task execution/history, but allow an explicit template sync to
# update only the separated normal-review configuration for existing tasks.
_sync_normal_review_snapshot_preserving_history(task, template=template)
task.updated_by_user_id = user_id
if not safe_system_rollout:
# Preserve the pre-existing explicit/manual sync behaviour.
_sync_normal_review_snapshot_preserving_history(task, template=template)
task.updated_by_user_id = user_id
# Automatic system rollout never rewrites a started/completed/reviewed
# task snapshot. Audit/review history remains exactly as performed.
result["preserved_history"] += 1
if safe_system_rollout and inactive_templates:
inactive_ids = {int(row.id) for row in inactive_templates}
for task in existing:
if task.firm_task_template_id is None or int(task.firm_task_template_id) not in inactive_ids:
continue
status = (task.status or "pending").strip().lower()
never_started = (
status == "pending"
and task.started_at_utc is None
and task.completed_at_utc is None
and task.submitted_for_review_at_utc is None
and (task.rework_status or "none") == "none"
and not bool(getattr(task, "is_locked", False))
)
if never_started and bool(getattr(task, "is_active", True)):
task.is_active = False
task.updated_by_user_id = user_id
result["deactivated_pending"] += 1
elif not never_started:
result["preserved_history"] += 1
return result