Add task role eligibility and safe open engagement sync
This commit is contained in:
@@ -36,6 +36,11 @@ from app.modules.services.due_dates import (
|
||||
parse_optional_date,
|
||||
)
|
||||
from app.modules.services.catalogue_merge import build_merge_preview, merge_service_catalogues
|
||||
from app.modules.services.execution import (
|
||||
TASK_EXECUTION_ROLES,
|
||||
serialise_eligible_task_roles,
|
||||
sync_open_engagement_tasks_for_service,
|
||||
)
|
||||
from app.modules.services.task_documents import (
|
||||
create_task_document_requirement,
|
||||
get_task_document_requirement,
|
||||
@@ -79,6 +84,7 @@ def _base_ctx(request: Request, user, db, **ctx):
|
||||
"engagement_type_choices": ENGAGEMENT_TYPE_CHOICES,
|
||||
"due_period_types": DUE_PERIOD_TYPES,
|
||||
"due_year_basis_choices": DUE_YEAR_BASIS_CHOICES,
|
||||
"task_execution_roles": TASK_EXECUTION_ROLES,
|
||||
}
|
||||
base.update(ctx)
|
||||
return base
|
||||
@@ -939,6 +945,7 @@ def _copy_system_defaults_if_firm_tasks_empty(
|
||||
description=default.description,
|
||||
sequence_no=default.sequence_no,
|
||||
default_role_name=default.default_role_name,
|
||||
eligible_role_names=getattr(default, "eligible_role_names", None) or default.default_role_name,
|
||||
is_mandatory=default.is_mandatory,
|
||||
requires_review=default.requires_review,
|
||||
is_aqmm_task=getattr(default, "is_aqmm_task", False),
|
||||
@@ -1234,7 +1241,7 @@ def task_templates_detail(request: Request, catalogue_id: int):
|
||||
|
||||
|
||||
@router.post('/templates/{catalogue_id}/tasks/new')
|
||||
def task_template_create_submit(request: Request, catalogue_id: int, task_name: str = Form(...), description: str = Form(''), default_role_name: str = Form(''), sequence_no: int | None = Form(None), is_mandatory: str | None = Form(None), requires_review: str | None = Form(None), task_category: str = Form(''), response_required: str | None = Form(None), response_type: str = Form('NONE'), evidence_required: str | None = Form(None), remarks_required_if_no: str | None = Form(None), is_aqmm_task: str | None = Form(None), aqmm_mandatory: str | None = Form(None), aqmm_evidence_required: str | None = Form(None), aqmm_manager_review_required: str | None = Form(None), aqmm_partner_review_required: str | None = Form(None), aqmm_review_partner_required: str | None = Form(None), aqmm_blocks_final_release: str | None = Form(None), aqmm_reference: str = Form(''), is_active: str | None = Form(None), csrf_token: str = Form(...)):
|
||||
def task_template_create_submit(request: Request, catalogue_id: int, task_name: str = Form(...), description: str = Form(''), default_role_name: str = Form(''), eligible_roles: list[str] = Form([]), sequence_no: int | None = Form(None), is_mandatory: str | None = Form(None), requires_review: str | None = Form(None), task_category: str = Form(''), response_required: str | None = Form(None), response_type: str = Form('NONE'), evidence_required: str | None = Form(None), remarks_required_if_no: str | None = Form(None), is_aqmm_task: str | None = Form(None), aqmm_mandatory: str | None = Form(None), aqmm_evidence_required: str | None = Form(None), aqmm_manager_review_required: str | None = Form(None), aqmm_partner_review_required: str | None = Form(None), aqmm_review_partner_required: str | None = Form(None), aqmm_blocks_final_release: str | None = Form(None), aqmm_reference: str = Form(''), is_active: str | None = Form(None), csrf_token: str = Form(...)):
|
||||
validate_csrf(request, csrf_token)
|
||||
db = CommonSessionLocal()
|
||||
try:
|
||||
@@ -1256,6 +1263,7 @@ def task_template_create_submit(request: Request, catalogue_id: int, task_name:
|
||||
task_name=task_name.strip(),
|
||||
description=description.strip() or None,
|
||||
default_role_name=default_role_name.strip() or None,
|
||||
eligible_role_names=serialise_eligible_task_roles(eligible_roles, default_role_name),
|
||||
sequence_no=sequence_no or next_task_sequence(db, tenant_id=tenant_id, catalogue_id=catalogue_id),
|
||||
is_mandatory=is_mandatory is not None,
|
||||
requires_review=requires_review is not None,
|
||||
@@ -1602,6 +1610,48 @@ def firm_task_template_toggle_active(
|
||||
db.close()
|
||||
|
||||
|
||||
@router.post('/templates/{catalogue_id}/sync-open-engagements')
|
||||
def sync_firm_tasks_to_open_engagements(
|
||||
request: Request,
|
||||
catalogue_id: int,
|
||||
include_started_open_tasks: str | None = Form(None),
|
||||
csrf_token: str = Form(...),
|
||||
):
|
||||
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)
|
||||
|
||||
result = sync_open_engagement_tasks_for_service(
|
||||
db,
|
||||
tenant_id=tenant_id,
|
||||
catalogue_id=catalogue_id,
|
||||
user_id=user.id,
|
||||
include_started_open_tasks=include_started_open_tasks is not None,
|
||||
)
|
||||
db.commit()
|
||||
return RedirectResponse(
|
||||
url=(
|
||||
f'/services/templates/{catalogue_id}'
|
||||
f'?synced=1&created={result["created"]}'
|
||||
f'&updated_pending={result["updated_pending"]}'
|
||||
f'&updated_started={result["updated_started"]}'
|
||||
f'&preserved={result["preserved_history"]}'
|
||||
),
|
||||
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()
|
||||
@@ -1653,6 +1703,7 @@ def firm_task_template_edit_submit(
|
||||
task_name: str = Form(...),
|
||||
description: str = Form(''),
|
||||
default_role_name: str = Form(''),
|
||||
eligible_roles: list[str] = Form([]),
|
||||
sequence_no: int = Form(1),
|
||||
is_mandatory: str | None = Form(None),
|
||||
requires_review: str | None = Form(None),
|
||||
@@ -1670,6 +1721,8 @@ def firm_task_template_edit_submit(
|
||||
aqmm_blocks_final_release: str | None = Form(None),
|
||||
aqmm_reference: str = Form(''),
|
||||
is_active: str | None = Form(None),
|
||||
sync_open_engagements: str | None = Form(None),
|
||||
sync_started_open_tasks: str | None = Form(None),
|
||||
csrf_token: str = Form(...),
|
||||
):
|
||||
validate_csrf(request, csrf_token)
|
||||
@@ -1696,6 +1749,7 @@ def firm_task_template_edit_submit(
|
||||
task.task_name = task_name.strip()
|
||||
task.description = description.strip() or None
|
||||
task.default_role_name = default_role_name.strip() or None
|
||||
task.eligible_role_names = serialise_eligible_task_roles(eligible_roles, default_role_name)
|
||||
task.sequence_no = sequence_no
|
||||
task.is_mandatory = is_mandatory is not None
|
||||
task.requires_review = requires_review is not None
|
||||
@@ -1715,7 +1769,28 @@ def firm_task_template_edit_submit(
|
||||
task.is_active = is_active is not None
|
||||
task.updated_by_user_id = user.id
|
||||
|
||||
sync_result = None
|
||||
if sync_open_engagements is not None:
|
||||
sync_result = sync_open_engagement_tasks_for_service(
|
||||
db,
|
||||
tenant_id=tenant_id,
|
||||
catalogue_id=catalogue_id,
|
||||
user_id=user.id,
|
||||
include_started_open_tasks=sync_started_open_tasks is not None,
|
||||
)
|
||||
|
||||
db.commit()
|
||||
if sync_result is not None:
|
||||
return RedirectResponse(
|
||||
url=(
|
||||
f'/services/templates/{catalogue_id}'
|
||||
f'?synced=1&created={sync_result["created"]}'
|
||||
f'&updated_pending={sync_result["updated_pending"]}'
|
||||
f'&updated_started={sync_result["updated_started"]}'
|
||||
f'&preserved={sync_result["preserved_history"]}'
|
||||
),
|
||||
status_code=303,
|
||||
)
|
||||
return RedirectResponse(url=f'/services/templates/{catalogue_id}', status_code=303)
|
||||
finally:
|
||||
db.close()
|
||||
@@ -1770,6 +1845,7 @@ def default_task_template_edit_submit(
|
||||
task_name: str = Form(...),
|
||||
description: str = Form(''),
|
||||
default_role_name: str = Form(''),
|
||||
eligible_roles: list[str] = Form([]),
|
||||
sequence_no: int = Form(1),
|
||||
is_mandatory: str | None = Form(None),
|
||||
requires_review: str | None = Form(None),
|
||||
@@ -1815,6 +1891,7 @@ def default_task_template_edit_submit(
|
||||
task.task_name = task_name.strip()
|
||||
task.description = description.strip() or None
|
||||
task.default_role_name = default_role_name.strip() or None
|
||||
task.eligible_role_names = serialise_eligible_task_roles(eligible_roles, default_role_name)
|
||||
task.sequence_no = sequence_no
|
||||
task.is_mandatory = is_mandatory is not None
|
||||
task.requires_review = requires_review is not None
|
||||
|
||||
Reference in New Issue
Block a user