diff --git a/app/modules/services/templates/services/catalogue_detail.html b/app/modules/services/templates/services/catalogue_detail.html
index bacfaee..0beaf93 100644
--- a/app/modules/services/templates/services/catalogue_detail.html
+++ b/app/modules/services/templates/services/catalogue_detail.html
@@ -145,12 +145,111 @@
- System Default Tasks
{% if can_edit %}
Manage{% endif %}
+
+
+
System Default Tasks
+
System Admin controls the standard task template used as the base for firms.
+
+ {% if is_system_admin and can_edit %}
+
Manage Defaults
+ {% endif %}
+
+
{% for task in default_templates %}
-
{{ task.sequence_no }}. {{ task.task_name }}
Role: {{ task.default_role_name or '-' }} · Mandatory: {{ 'Yes' if task.is_mandatory else 'No' }} · Review: {{ 'Yes' if task.requires_review else 'No' }}
{% if task.description %}
{{ task.description }}
{% endif %}
- {% else %}
No system default tasks configured yet.
{% endfor %}
+
+
+
+
{{ task.sequence_no }}. {{ task.task_name }}
+
+ Role: {{ task.default_role_name or '-' }} ·
+ Mandatory: {{ 'Yes' if task.is_mandatory else 'No' }} ·
+ Review: {{ 'Yes' if task.requires_review else 'No' }} ·
+ {{ 'Active' if task.is_active else 'Inactive' }}
+
+ {% if task.description %}
{{ task.description }}
{% endif %}
+
+ {% if is_system_admin and can_edit %}
+
+ Edit
+
+ {% endif %}
+
+
+ {% else %}
+
No system default tasks configured yet.
+ {% endfor %}
+
+ {% if current_selection and current_selection.is_enabled %}
+
+
+
+
Firm Task Configuration
+
+ Firm Admin can edit, disable or enable tasks for this firm and add extra firm-only tasks.
+ System defaults are not changed.
+
+
+ {% if can_manage_firm_tasks %}
+
+ {% endif %}
+
+
+
+ {% for task in current_templates %}
+
+
+
+
+
{{ task.sequence_no }}. {{ task.task_name }}
+
+ {{ 'Enabled for Firm' if task.is_active else 'Disabled for Firm' }}
+
+
+
+ Role: {{ task.default_role_name or '-' }} ·
+ Mandatory: {{ 'Yes' if task.is_mandatory else 'No' }} ·
+ Review: {{ 'Yes' if task.requires_review else 'No' }}
+
+ {% if task.description %}
{{ task.description }}
{% endif %}
+
+
+ {% if can_manage_firm_tasks %}
+
+ {% endif %}
+
+
+ {% else %}
+
+ No firm task templates are configured yet. Use Add / Manage Firm Tasks to copy defaults or add firm-specific tasks.
+
+ {% endfor %}
+
+
+
+ Editing or disabling a firm task affects future task generation only. Existing engagement task instances remain unchanged.
+
+
+ {% endif %}
{% endblock %}
diff --git a/app/modules/services/templates/services/task_template_detail.html b/app/modules/services/templates/services/task_template_detail.html
index cade5b2..8d11db8 100644
--- a/app/modules/services/templates/services/task_template_detail.html
+++ b/app/modules/services/templates/services/task_template_detail.html
@@ -186,7 +186,21 @@
{% endif %}
- {% if can_manage_tasks %}Edit{% endif %}
+ {% if can_manage_tasks %}
+
+ {% endif %}
|
{% else %}
diff --git a/app/modules/services/ui.py b/app/modules/services/ui.py
index a3267b4..a8ffa68 100644
--- a/app/modules/services/ui.py
+++ b/app/modules/services/ui.py
@@ -602,6 +602,8 @@ def catalogue_detail(request: Request, catalogue_id: int):
catalogue=row,
can_edit=can_edit,
can_manage_firm_services=_can_manage_firm_services(db, user),
+ can_manage_firm_tasks=_can_manage_firm_tasks(db, user),
+ is_system_admin=_is_system_admin(db, user),
branches=branches,
current_selection=get_firm_selection(db, tenant_id=tenant_id, catalogue_id=row.id),
current_templates=get_firm_task_templates(db, tenant_id=tenant_id, catalogue_id=row.id),
@@ -1548,6 +1550,58 @@ def firm_task_document_template_download(request: Request, template_id: int):
db.close()
+@router.post('/templates/{catalogue_id}/tasks/{task_id}/toggle-active')
+def firm_task_template_toggle_active(
+ request: Request,
+ catalogue_id: int,
+ task_id: int,
+ csrf_token: str = Form(...),
+):
+ """Enable/disable a firm task template without changing the system default.
+
+ Existing engagement task instances are snapshots and are intentionally not
+ modified. This affects task generation for future engagements only.
+ """
+ validate_csrf(request, csrf_token)
+ db = CommonSessionLocal()
+ try:
+ user = get_current_user(request, db=db)
+ if not user:
+ return RedirectResponse(url='/login', status_code=303)
+
+ if not _can_manage_firm_tasks(db, user):
+ return _redirect_denied()
+
+ tenant_id = _active_tenant_id(request, user)
+ selection = get_firm_selection(db, tenant_id=tenant_id, catalogue_id=catalogue_id)
+ if not selection or not selection.is_enabled:
+ return RedirectResponse(url='/services', status_code=303)
+
+ task = get_firm_task_template(
+ db,
+ tenant_id=tenant_id,
+ catalogue_id=catalogue_id,
+ task_id=task_id,
+ )
+ if not task:
+ return RedirectResponse(
+ url=f'/services/templates/{catalogue_id}?error=task_missing',
+ status_code=303,
+ )
+
+ task.is_active = not bool(task.is_active)
+ task.updated_by_user_id = user.id
+ db.commit()
+
+ state = 'enabled' if task.is_active else 'disabled'
+ return RedirectResponse(
+ url=f'/services/templates/{catalogue_id}?task_{state}=1',
+ status_code=303,
+ )
+ finally:
+ db.close()
+
+
@router.get('/templates/{catalogue_id}/tasks/{task_id}/edit')
def firm_task_template_edit_page(request: Request, catalogue_id: int, task_id: int):
db = CommonSessionLocal()