Reconcile firm tasks fully with system defaults

This commit is contained in:
A R R R Associates
2026-09-19 16:02:07 +05:30
parent 5cee4f8de4
commit 53732a7270
3 changed files with 259 additions and 56 deletions
+20 -49
View File
@@ -29,6 +29,7 @@ from app.modules.services.default_tasks_export import build_default_tasks_export
from app.modules.services.firm_tasks_export import build_firm_tasks_export
from app.modules.services.default_task_sync import (
accept_system_update_for_firm_task,
fully_align_firm_tasks_to_system_defaults,
keep_firm_customization_for_system_revision,
mark_firm_task_customized,
sync_firm_tasks_from_system_defaults,
@@ -1652,12 +1653,13 @@ def firm_tasks_accept_all_system_updates(
catalogue_id: int,
csrf_token: str = Form(...),
):
"""Upgrade every pending firm-task system revision for the active firm/service.
"""Fully reconcile this firm's service checklist to the current system master.
Firm-only tasks are intentionally untouched. Existing per-task upgrade/keep actions
remain available. Engagement synchronization runs once after all template updates so
pending/unstarted open-engagement tasks are refreshed safely without rewriting
started/completed/reviewed history.
Existing task-by-task Upgrade / Keep controls remain unchanged. This explicit bulk
action aligns every reliably system-derived firm task, retires rows whose system
source is retired, resolves duplicate inherited rows, restores the exact active
system sequence, and preserves genuine firm-only tasks. Engagement synchronization
runs once using the existing safe-history rules.
"""
validate_csrf(request, csrf_token)
db = CommonSessionLocal()
@@ -1673,58 +1675,27 @@ def firm_tasks_accept_all_system_updates(
if not selection or not selection.is_enabled:
return RedirectResponse(url='/services', status_code=303)
pending_tasks = db.scalars(
select(FirmServiceTaskTemplate)
.where(
FirmServiceTaskTemplate.tenant_id == tenant_id,
FirmServiceTaskTemplate.service_catalogue_id == catalogue_id,
FirmServiceTaskTemplate.system_update_available.is_(True),
FirmServiceTaskTemplate.source_system_task_id.is_not(None),
)
.order_by(FirmServiceTaskTemplate.sequence_no, FirmServiceTaskTemplate.id)
).all()
if not pending_tasks:
return RedirectResponse(
url=f'/services/templates/{catalogue_id}?system_bulk_none=1',
status_code=303,
)
upgraded = 0
retired = 0
for task in pending_tasks:
source = db.get(ServiceDefaultTaskTemplate, int(task.source_system_task_id))
if source is None:
continue
if not bool(source.is_active):
retired += 1
accept_system_update_for_firm_task(
db,
task=task,
user_id=user.id,
sync_open_engagements=False,
)
upgraded += 1
engagement = sync_open_engagement_tasks_for_service(
result = fully_align_firm_tasks_to_system_defaults(
db,
tenant_id=tenant_id,
catalogue_id=catalogue_id,
user_id=user.id,
include_started_open_tasks=False,
safe_system_rollout=True,
service_catalogue_id=catalogue_id,
updated_by_user_id=user.id,
sync_open_engagements=True,
)
db.commit()
aligned = result.created + result.updated + result.unchanged
return RedirectResponse(
url=(
f'/services/templates/{catalogue_id}?system_bulk_upgraded=1'
f'&bulk_count={upgraded}'
f'&bulk_retired={retired}'
f'&engagement_created={engagement.get("created", 0)}'
f'&engagement_updated={engagement.get("updated_pending", 0)}'
f'&engagement_deactivated={engagement.get("deactivated_pending", 0)}'
f'&engagement_preserved={engagement.get("preserved_history", 0)}'
f'&bulk_count={aligned}'
f'&bulk_retired={result.retired}'
f'&bulk_created={result.created}'
f'&bulk_linked_legacy={result.linked_legacy}'
f'&engagement_created={result.engagement_created}'
f'&engagement_updated={result.engagement_updated_pending}'
f'&engagement_deactivated={result.engagement_deactivated_pending}'
f'&engagement_preserved={result.engagement_preserved_history}'
),
status_code=303,
)