Move AQMM controls to assurance engagement workflow

This commit is contained in:
A R R R Associates
2026-07-07 10:29:27 +05:30
parent cd355d6fc5
commit 05c882304b
10 changed files with 943 additions and 82 deletions
+177
View File
@@ -26,6 +26,16 @@ from app.modules.services.client_services import (
list_review_partners,
parse_date,
review_partner_required_for_engagement,
ensure_engagement_quality_workflow,
enforce_quality_gate_on_subscription,
request_engagement_quality_declarations,
list_engagement_quality_declarations,
respond_engagement_quality_declaration,
verify_engagement_kyc_from_permanent_documents,
get_latest_engagement_kyc_verification,
get_current_engagement_letter,
mark_engagement_letter_completed,
approve_engagement_quality_workflow,
)
from app.modules.core.rbac.deps import get_user_permissions, get_user_roles
from app.modules.core.rbac.permission_guard import require_permission
@@ -300,6 +310,8 @@ def subscription_create_submit(
row.is_active = is_active is not None
row.updated_by_user_id = user.id
apply_due_date_rule_to_subscription(db, row)
ensure_engagement_quality_workflow(db, subscription=row, actor_user_id=user.id, create_declarations=False)
enforce_quality_gate_on_subscription(row)
db.commit()
db.refresh(row)
@@ -380,6 +392,13 @@ def subscription_detail(request: Request, subscription_id: int):
if row.financial_year != active_fy:
return RedirectResponse(url=f"/services/engagements?financial_year={active_fy}", status_code=303)
ensure_engagement_quality_workflow(db, subscription=row, actor_user_id=user.id, create_declarations=False)
db.flush()
declarations = list_engagement_quality_declarations(db, subscription_id=row.id)
my_pending_declarations = [d for d in declarations if d.requested_user_id == user.id and d.status == "pending"]
kyc_verification = get_latest_engagement_kyc_verification(db, subscription_id=row.id)
engagement_letter = get_current_engagement_letter(db, subscription_id=row.id)
tasks = db.execute(
select(ClientServiceTaskInstance)
.where(ClientServiceTaskInstance.subscription_id == row.id)
@@ -394,12 +413,168 @@ def subscription_detail(request: Request, subscription_id: int):
title="Engagement Subscription",
row=row,
tasks=tasks,
declarations=declarations,
my_pending_declarations=my_pending_declarations,
kyc_verification=kyc_verification,
engagement_letter=engagement_letter,
can_manage=_can_manage_client_services(db, user),
)
finally:
db.close()
@router.post("/{subscription_id}/aqmm/initiate")
def subscription_aqmm_initiate(request: Request, subscription_id: int, 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)
try:
require_permission(db, user, "clients.edit")
except Exception:
return _redirect_denied()
tenant_id = _active_tenant_id(request, user)
row = get_subscription(db, subscription_id=subscription_id, tenant_id=tenant_id)
if row:
ensure_engagement_quality_workflow(db, subscription=row, actor_user_id=user.id, create_declarations=True)
enforce_quality_gate_on_subscription(row)
db.commit()
return RedirectResponse(url=f"/services/engagements/{subscription_id}", status_code=303)
finally:
db.close()
@router.post("/{subscription_id}/aqmm/request-declarations")
def subscription_aqmm_request_declarations(request: Request, subscription_id: int, 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)
try:
require_permission(db, user, "clients.edit")
except Exception:
return _redirect_denied()
tenant_id = _active_tenant_id(request, user)
row = get_subscription(db, subscription_id=subscription_id, tenant_id=tenant_id)
if row:
request_engagement_quality_declarations(db, subscription=row, actor_user_id=user.id)
enforce_quality_gate_on_subscription(row)
db.commit()
return RedirectResponse(url=f"/services/engagements/{subscription_id}", status_code=303)
finally:
db.close()
@router.post("/{subscription_id}/aqmm/declarations/{declaration_id}/respond")
def subscription_aqmm_declaration_respond(
request: Request,
subscription_id: int,
declaration_id: int,
status: str = Form(...),
notes: str = Form(""),
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)
respond_engagement_quality_declaration(
db,
declaration_id=declaration_id,
current_user_id=user.id,
status=status,
notes=notes,
request=request,
)
db.commit()
return RedirectResponse(url=f"/services/engagements/{subscription_id}", status_code=303)
finally:
db.close()
@router.post("/{subscription_id}/aqmm/kyc/verify")
def subscription_aqmm_kyc_verify(request: Request, subscription_id: int, notes: str = Form(""), 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)
try:
require_permission(db, user, "clients.edit")
except Exception:
return _redirect_denied()
tenant_id = _active_tenant_id(request, user)
row = get_subscription(db, subscription_id=subscription_id, tenant_id=tenant_id)
if row:
verify_engagement_kyc_from_permanent_documents(db, subscription=row, actor_user_id=user.id, notes=notes)
enforce_quality_gate_on_subscription(row)
db.commit()
return RedirectResponse(url=f"/services/engagements/{subscription_id}", status_code=303)
finally:
db.close()
@router.post("/{subscription_id}/aqmm/engagement-letter/complete")
def subscription_aqmm_engagement_letter_complete(
request: Request,
subscription_id: int,
acceptance_mode: str = Form(...),
notes: str = Form(""),
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)
try:
require_permission(db, user, "clients.edit")
except Exception:
return _redirect_denied()
tenant_id = _active_tenant_id(request, user)
row = get_subscription(db, subscription_id=subscription_id, tenant_id=tenant_id)
if row:
mark_engagement_letter_completed(db, subscription=row, actor_user_id=user.id, acceptance_mode=acceptance_mode, notes=notes, request=request)
enforce_quality_gate_on_subscription(row)
db.commit()
return RedirectResponse(url=f"/services/engagements/{subscription_id}", status_code=303)
finally:
db.close()
@router.post("/{subscription_id}/aqmm/approve")
def subscription_aqmm_approve(request: Request, subscription_id: int, 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)
try:
require_permission(db, user, "clients.edit")
except Exception:
return _redirect_denied()
tenant_id = _active_tenant_id(request, user)
row = get_subscription(db, subscription_id=subscription_id, tenant_id=tenant_id)
if row:
try:
approve_engagement_quality_workflow(db, subscription=row, actor_user_id=user.id)
db.commit()
except ValueError:
db.rollback()
return RedirectResponse(url=f"/services/engagements/{subscription_id}", status_code=303)
finally:
db.close()
@router.get("/{subscription_id}/edit")
def subscription_edit_page(request: Request, subscription_id: int):
db = CommonSessionLocal()
@@ -503,6 +678,8 @@ def subscription_edit_submit(
row.is_active = is_active is not None
row.updated_by_user_id = user.id
apply_due_date_rule_to_subscription(db, row)
ensure_engagement_quality_workflow(db, subscription=row, actor_user_id=user.id, create_declarations=False)
enforce_quality_gate_on_subscription(row)
db.commit()
return RedirectResponse(url=f"/services/engagements/{row.id}", status_code=303)
finally: