Separate normal task review from AQMM review

This commit is contained in:
A R R R Associates
2026-08-11 09:05:09 +05:30
parent 20fd30ff3d
commit c3684b7afa
17 changed files with 435 additions and 98 deletions
+31 -10
View File
@@ -446,16 +446,21 @@ def _partner_task_category(task: ClientServiceTaskInstance) -> str:
def _partner_review_level_for_task(task: ClientServiceTaskInstance, subscription: ClientServiceSubscription, current_user) -> str | None:
"""Return the review level the current partner is authorised to perform.
Review Partner work is kept separate from Engagement Partner work. System and
Firm Admin users may inspect the workspace, but review decisions are selected
from the engagement assignments rather than from a new permission model.
"""
"""Return the review level the current partner is authorised to perform."""
uid = int(getattr(current_user, "id", 0) or 0)
is_review_partner = uid and uid == int(getattr(subscription, "review_partner_user_id", 0) or 0)
is_engagement_partner = uid and uid == int(getattr(subscription, "assigned_partner_user_id", 0) or 0)
normal_role = (getattr(task, "normal_review_role", None) or "").strip().lower()
normal_status = (getattr(task, "normal_review_status", None) or "not_required").strip().lower()
if (
is_engagement_partner
and getattr(task, "normal_review_required", False)
and normal_role in {"partner", "manager_or_partner"}
and normal_status in {"pending", "reviewed", "rework_required"}
):
return "normal_partner"
if is_review_partner and getattr(task, "aqmm_review_partner_required", False):
return "review_partner"
if is_engagement_partner and getattr(task, "aqmm_partner_review_required", False):
@@ -464,6 +469,14 @@ def _partner_review_level_for_task(task: ClientServiceTaskInstance, subscription
def _partner_review_state(task: ClientServiceTaskInstance, review_level: str | None) -> str:
if review_level == "normal_partner":
status = (getattr(task, "normal_review_status", "not_required") or "not_required").strip().lower()
if status == "reviewed":
return "reviewed"
if status == "rework_required" or getattr(task, "rework_status", "none") == "open":
return "rework"
return "pending_review" if status == "pending" else "not_ready"
if getattr(task, "rework_status", "none") == "open":
return "rework"
if review_level == "review_partner":
@@ -476,10 +489,8 @@ def _partner_review_state(task: ClientServiceTaskInstance, review_level: str | N
return "reviewed"
if status == "rework_required":
return "rework"
# Partner review must follow any required Manager review.
if getattr(task, "aqmm_manager_review_required", False) and getattr(task, "manager_review_status", "not_required") != "reviewed":
return "not_ready"
# Review Partner review must follow required Engagement Partner review.
if review_level == "review_partner" and getattr(task, "aqmm_partner_review_required", False) and getattr(task, "partner_review_status", "not_required") != "reviewed":
return "not_ready"
if (getattr(task, "status", "pending") or "pending") not in CLOSED_TASK_STATUSES and getattr(task, "submitted_for_review_at_utc", None) is None:
@@ -523,7 +534,10 @@ def _partner_task_payload(task: ClientServiceTaskInstance, subscription: ClientS
"blocks_final_release": bool(getattr(task, "aqmm_blocks_final_release", False)),
"partner_review_required": bool(getattr(task, "aqmm_partner_review_required", False)),
"review_partner_required": bool(getattr(task, "aqmm_review_partner_required", False)),
"normal_review_status": getattr(task, "normal_review_status", "not_required"),
"normal_review_note": getattr(task, "normal_review_note", None),
"review_level": review_level,
"review_kind_label": "Normal Review" if review_level == "normal_partner" else ("AQMM Review Partner" if review_level == "review_partner" else ("AQMM Partner Review" if review_level == "partner" else "")),
"review_state": review_state,
"can_review": review_level is not None and review_state in {"pending_review", "reviewed", "rework"},
"is_exception": getattr(task, "checklist_response", None) == "NO" or getattr(task, "rework_status", "none") == "open",
@@ -562,12 +576,18 @@ def _partner_review_queue_rows(db: Session, request, current_user, *, limit: int
ClientServiceTaskInstance.is_active.is_(True),
)
tasks = list(db.execute(task_stmt.order_by(ClientServiceTaskInstance.sequence_no.asc(), ClientServiceTaskInstance.id.asc())).scalars().all())
pending_normal_partner = sum(
1 for t in tasks
if getattr(t, "normal_review_required", False)
and (getattr(t, "normal_review_role", None) or "").strip().lower() in {"partner", "manager_or_partner"}
and (getattr(t, "normal_review_status", None) or "not_required") in {"pending", "rework_required"}
)
pending_partner = sum(1 for t in tasks if getattr(t, "aqmm_partner_review_required", False) and getattr(t, "partner_review_status", "not_required") != "reviewed")
pending_review_partner = sum(1 for t in tasks if getattr(t, "aqmm_review_partner_required", False) and getattr(t, "review_partner_review_status", "not_required") != "reviewed")
rework = sum(1 for t in tasks if getattr(t, "rework_status", "none") == "open")
blockers = sum(1 for t in tasks if getattr(t, "aqmm_blocks_final_release", False) and getattr(t, "aqmm_status", "not_required") != "completed")
exceptions = sum(1 for t in tasks if getattr(t, "checklist_response", None) == "NO")
if not any((pending_partner, pending_review_partner, rework, blockers, exceptions)):
if not any((pending_normal_partner, pending_partner, pending_review_partner, rework, blockers, exceptions)):
continue
weighted = _weighted_progress(tasks)
sla = _engagement_sla(sub, tasks)
@@ -576,6 +596,7 @@ def _partner_review_queue_rows(db: Session, request, current_user, *, limit: int
"client_name": getattr(getattr(sub, "client", None), "client_name", None) or "Unlinked Client",
"service_name": getattr(getattr(sub, "catalogue", None), "service_name", None) or "Service",
"financial_year": sub.financial_year or "-",
"pending_normal_partner": pending_normal_partner,
"pending_partner": pending_partner,
"pending_review_partner": pending_review_partner,
"rework_count": rework,
@@ -585,7 +606,7 @@ def _partner_review_queue_rows(db: Session, request, current_user, *, limit: int
"sla": sla,
"href": f"/partner/reviews/engagements/{sub.id}",
})
rows.sort(key=lambda r: (r["release_blockers"], r["rework_count"], r["pending_partner"] + r["pending_review_partner"]), reverse=True)
rows.sort(key=lambda r: (r["release_blockers"], r["rework_count"], r["pending_normal_partner"] + r["pending_partner"] + r["pending_review_partner"]), reverse=True)
return rows