Auto lock completed non assurance engagements

This commit is contained in:
A R R R Associates
2026-08-11 19:40:53 +05:30
parent 7d2a3ee5d9
commit eb18a5695f
+72
View File
@@ -11,6 +11,7 @@ from app.core.templating import templates
from app.modules.services.models import ClientServiceSubscription, ClientServiceTaskInstance
from app.modules.services.due_dates import apply_due_date_rule_to_subscription
from app.modules.services.execution import (
CLOSED_TASK_STATUSES,
aqmm_task_summary_for_subscription,
generate_tasks_for_subscription_if_ready,
update_engagement_closure_from_sources,
@@ -151,6 +152,60 @@ def _lock_subscription_row(row: ClientServiceSubscription, user) -> bool:
return True
def _auto_lock_completed_non_assurance_subscription(
db,
row: ClientServiceSubscription,
user,
) -> bool:
"""Lock a completed non-assurance engagement without touching its plan.
Completion here means every active task is closed, every required normal
review is reviewed, every required AQMM task-review flag (if any) is
reviewed, and no task has open rework. Assurance engagements deliberately
remain on the existing AQMM/final-release closure workflow.
"""
if getattr(row, "is_locked", False):
return False
if (getattr(row, "engagement_type", None) or "non_assurance").strip().lower() == "assurance":
return False
tasks = list(
db.execute(
select(ClientServiceTaskInstance).where(
ClientServiceTaskInstance.subscription_id == row.id,
ClientServiceTaskInstance.is_active.is_(True),
)
).scalars().all()
)
if not tasks:
return False
for task in tasks:
status = (getattr(task, "status", None) or "pending").strip().lower()
if status not in CLOSED_TASK_STATUSES:
return False
if getattr(task, "normal_review_required", False):
if (getattr(task, "normal_review_status", None) or "not_required").strip().lower() != "reviewed":
return False
if getattr(task, "aqmm_manager_review_required", False):
if (getattr(task, "manager_review_status", None) or "not_required").strip().lower() != "reviewed":
return False
if getattr(task, "aqmm_partner_review_required", False):
if (getattr(task, "partner_review_status", None) or "not_required").strip().lower() != "reviewed":
return False
if getattr(task, "aqmm_review_partner_required", False):
if (getattr(task, "review_partner_review_status", None) or "not_required").strip().lower() != "reviewed":
return False
if (getattr(task, "rework_status", None) or "none").strip().lower() == "open":
return False
return _lock_subscription_row(row, user)
@router.get("")
def subscription_list(
request: Request,
@@ -184,6 +239,13 @@ def subscription_list(
q=q,
include_inactive=include_inactive,
)
auto_locked = 0
for row in rows:
if _auto_lock_completed_non_assurance_subscription(db, row, user):
auto_locked += 1
if auto_locked:
db.commit()
return _render(
request,
"modules/services/templates/services/engagements/list.html",
@@ -731,6 +793,10 @@ 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)
if _auto_lock_completed_non_assurance_subscription(db, row, user):
db.commit()
db.refresh(row)
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)
@@ -1055,6 +1121,9 @@ def subscription_edit_page(request: Request, subscription_id: int):
active_fy = _active_financial_year(request)
if row.financial_year != active_fy:
return RedirectResponse(url=f"/services/engagements?financial_year={active_fy}", status_code=303)
if _auto_lock_completed_non_assurance_subscription(db, row, user):
db.commit()
db.refresh(row)
if getattr(row, "is_locked", False) or is_row_financial_year_locked(db, row):
return RedirectResponse(url=f"/services/engagements/{row.id}?year_locked=1", status_code=303)
@@ -1125,6 +1194,9 @@ def subscription_edit_submit(
active_fy = _active_financial_year(request)
if row.financial_year != active_fy:
return RedirectResponse(url=f"/services/engagements?financial_year={active_fy}", status_code=303)
if _auto_lock_completed_non_assurance_subscription(db, row, user):
db.commit()
db.refresh(row)
if getattr(row, "is_locked", False) or is_row_financial_year_locked(db, row):
return RedirectResponse(url=f"/services/engagements/{row.id}?year_locked=1", status_code=303)