Auto lock completed non assurance engagements
This commit is contained in:
@@ -11,6 +11,7 @@ from app.core.templating import templates
|
|||||||
from app.modules.services.models import ClientServiceSubscription, ClientServiceTaskInstance
|
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.due_dates import apply_due_date_rule_to_subscription
|
||||||
from app.modules.services.execution import (
|
from app.modules.services.execution import (
|
||||||
|
CLOSED_TASK_STATUSES,
|
||||||
aqmm_task_summary_for_subscription,
|
aqmm_task_summary_for_subscription,
|
||||||
generate_tasks_for_subscription_if_ready,
|
generate_tasks_for_subscription_if_ready,
|
||||||
update_engagement_closure_from_sources,
|
update_engagement_closure_from_sources,
|
||||||
@@ -151,6 +152,60 @@ def _lock_subscription_row(row: ClientServiceSubscription, user) -> bool:
|
|||||||
return True
|
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("")
|
@router.get("")
|
||||||
def subscription_list(
|
def subscription_list(
|
||||||
request: Request,
|
request: Request,
|
||||||
@@ -184,6 +239,13 @@ def subscription_list(
|
|||||||
q=q,
|
q=q,
|
||||||
include_inactive=include_inactive,
|
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(
|
return _render(
|
||||||
request,
|
request,
|
||||||
"modules/services/templates/services/engagements/list.html",
|
"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:
|
if row.financial_year != active_fy:
|
||||||
return RedirectResponse(url=f"/services/engagements?financial_year={active_fy}", status_code=303)
|
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)
|
ensure_engagement_quality_workflow(db, subscription=row, actor_user_id=user.id, create_declarations=False)
|
||||||
db.flush()
|
db.flush()
|
||||||
declarations = list_engagement_quality_declarations(db, subscription_id=row.id)
|
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)
|
active_fy = _active_financial_year(request)
|
||||||
if row.financial_year != active_fy:
|
if row.financial_year != active_fy:
|
||||||
return RedirectResponse(url=f"/services/engagements?financial_year={active_fy}", status_code=303)
|
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):
|
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)
|
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)
|
active_fy = _active_financial_year(request)
|
||||||
if row.financial_year != active_fy:
|
if row.financial_year != active_fy:
|
||||||
return RedirectResponse(url=f"/services/engagements?financial_year={active_fy}", status_code=303)
|
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):
|
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)
|
return RedirectResponse(url=f"/services/engagements/{row.id}?year_locked=1", status_code=303)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user