From 42746765134338d7ba3d89538acca339e5dad831 Mon Sep 17 00:00:00 2001 From: A R R R Associates Date: Mon, 3 Aug 2026 17:43:18 +0530 Subject: [PATCH] Auto initialise firm tasks from system defaults --- .../templates/services/catalogue_list.html | 29 +++++- app/modules/services/ui.py | 91 ++++++++++++++++++- 2 files changed, 118 insertions(+), 2 deletions(-) diff --git a/app/modules/services/templates/services/catalogue_list.html b/app/modules/services/templates/services/catalogue_list.html index 71d6ce9..edeb5b9 100644 --- a/app/modules/services/templates/services/catalogue_list.html +++ b/app/modules/services/templates/services/catalogue_list.html @@ -24,6 +24,15 @@ Bulk update completed: {{ request.query_params.get('bulk_updated', '0') }} changed, {{ request.query_params.get('bulk_unchanged', '0') }} already in the requested state, and {{ request.query_params.get('bulk_skipped', '0') }} skipped. + {% if request.query_params.get('bulk_action') == 'enable' %} +
+ {{ request.query_params.get('tasks_copied', '0') }} system-default tasks copied. + {{ request.query_params.get('services_existing_tasks', '0') }} services already had firm tasks and were preserved. + {% if request.query_params.get('services_without_defaults', '0') != '0' %} + {{ request.query_params.get('services_without_defaults', '0') }} services had no system-default tasks. + {% endif %} +
+ {% endif %} {% elif request.query_params.get('bulk_action') == 'no_selection' %}
Select at least one service before applying a bulk action.
@@ -33,9 +42,27 @@
The requested bulk action is invalid.
{% endif %} + + {% if request.query_params.get('service_action') == 'enabled' %} +
+ Service selected for the firm. + {% if request.query_params.get('existing_tasks') == '1' %} + Existing firm task templates were preserved without changes. + {% elif request.query_params.get('tasks_copied', '0') != '0' %} + {{ request.query_params.get('tasks_copied', '0') }} system-default tasks were copied automatically. + {% else %} + No system-default tasks were available to copy. + {% endif %} +
+ {% elif request.query_params.get('service_action') == 'disabled' %} +
+ Service disabled for the firm. Existing firm task templates were retained for future re-enablement. +
+ {% endif %} + {% if can_manage_firm_services %}
- Select the services your firm provides. Once selected, you can open Firm Task Templates and customise tasks for your firm. + Select the services your firm provides. System-default tasks are copied automatically only when that service has no existing firm task templates. Existing customised firm tasks are never overwritten.
{% endif %} diff --git a/app/modules/services/ui.py b/app/modules/services/ui.py index d1352c3..7370471 100644 --- a/app/modules/services/ui.py +++ b/app/modules/services/ui.py @@ -849,6 +849,56 @@ def catalogue_edit_submit(request: Request, catalogue_id: int, service_name: str db.close() +def _copy_system_defaults_if_firm_tasks_empty( + db, + *, + tenant_id: int, + catalogue_id: int, + user_id: int, +) -> tuple[int, bool]: + """Initialise firm task templates once without overwriting custom firm tasks.""" + existing_tasks = get_firm_task_templates( + db, + tenant_id=tenant_id, + catalogue_id=catalogue_id, + ) + if existing_tasks: + return 0, True + + defaults = get_default_task_templates(db, catalogue_id=catalogue_id) + copied_count = 0 + for default in defaults: + db.add(FirmServiceTaskTemplate( + tenant_id=tenant_id, + service_catalogue_id=catalogue_id, + task_name=default.task_name, + description=default.description, + sequence_no=default.sequence_no, + default_role_name=default.default_role_name, + is_mandatory=default.is_mandatory, + requires_review=default.requires_review, + task_category=getattr(default, "task_category", None), + response_required=getattr(default, "response_required", False), + response_type=getattr(default, "response_type", "NONE") or "NONE", + evidence_required=getattr(default, "evidence_required", False), + remarks_required_if_no=getattr(default, "remarks_required_if_no", False), + is_aqmm_task=getattr(default, "is_aqmm_task", False), + aqmm_mandatory=getattr(default, "aqmm_mandatory", False), + aqmm_evidence_required=getattr(default, "aqmm_evidence_required", False), + aqmm_manager_review_required=getattr(default, "aqmm_manager_review_required", False), + aqmm_partner_review_required=getattr(default, "aqmm_partner_review_required", False), + aqmm_review_partner_required=getattr(default, "aqmm_review_partner_required", False), + aqmm_blocks_final_release=getattr(default, "aqmm_blocks_final_release", False), + aqmm_reference=getattr(default, "aqmm_reference", None), + is_active=default.is_active, + created_by_user_id=user_id, + updated_by_user_id=user_id, + )) + copied_count += 1 + + return copied_count, False + + @router.post('/catalogue/bulk-selection') def bulk_update_firm_services( request: Request, @@ -900,6 +950,9 @@ def bulk_update_firm_services( updated_count = 0 unchanged_count = 0 skipped_count = 0 + tasks_copied_count = 0 + services_with_existing_tasks = 0 + services_without_defaults = 0 if action in {'enable', 'disable'} and unique_service_ids: catalogue_rows = db.execute( @@ -949,6 +1002,18 @@ def bulk_update_firm_services( updated_count += 1 else: unchanged_count += 1 + + copied_count, had_existing_tasks = _copy_system_defaults_if_firm_tasks_empty( + db, + tenant_id=tenant_id, + catalogue_id=catalogue_id, + user_id=user.id, + ) + tasks_copied_count += copied_count + if had_existing_tasks: + services_with_existing_tasks += 1 + elif copied_count == 0: + services_without_defaults += 1 else: if selection is not None and selection.is_enabled: selection.is_enabled = False @@ -966,6 +1031,9 @@ def bulk_update_firm_services( f'bulk_updated={updated_count}', f'bulk_unchanged={unchanged_count}', f'bulk_skipped={skipped_count}', + f'tasks_copied={tasks_copied_count}', + f'services_existing_tasks={services_with_existing_tasks}', + f'services_without_defaults={services_without_defaults}', f'page={max(1, return_page)}', f'per_page={return_per_page if return_per_page in (20, 50, 100) else 20}', ] @@ -1002,6 +1070,7 @@ def toggle_firm_service(request: Request, catalogue_id: int, default_branch_id: if not row or not row.is_active: return RedirectResponse(url='/services/catalogue', status_code=303) selection = get_firm_selection(db, tenant_id=tenant_id, catalogue_id=catalogue_id) + enabling = selection is None or not bool(selection.is_enabled) if not selection: selection = FirmServiceSelection( tenant_id=tenant_id, @@ -1017,8 +1086,28 @@ def toggle_firm_service(request: Request, catalogue_id: int, default_branch_id: if str(default_branch_id).strip(): selection.default_branch_id = int(default_branch_id) selection.updated_by_user_id = user.id + + copied_count = 0 + had_existing_tasks = False + if enabling: + copied_count, had_existing_tasks = _copy_system_defaults_if_firm_tasks_empty( + db, + tenant_id=tenant_id, + catalogue_id=catalogue_id, + user_id=user.id, + ) + db.commit() - return RedirectResponse(url='/services', status_code=303) + if enabling: + return RedirectResponse( + url=( + f'/services/catalogue?service_action=enabled' + f'&tasks_copied={copied_count}' + f'&existing_tasks={1 if had_existing_tasks else 0}' + ), + status_code=303, + ) + return RedirectResponse(url='/services/catalogue?service_action=disabled', status_code=303) finally: db.close()