Synchronise approved AQMM across staff and review boards

This commit is contained in:
A R R R Associates
2026-09-22 17:33:06 +05:30
parent ecdb93d6b5
commit 581f5faf80
4 changed files with 89 additions and 2 deletions
+26
View File
@@ -34,6 +34,7 @@ from app.modules.services.execution import (
apply_task_checklist_response,
recalculate_task_aqmm_status,
submit_task_for_review,
synchronise_approved_engagement_acceptance_tasks,
)
EMPLOYEE_STATUS = ["active", "inactive", "relieved"]
@@ -4077,6 +4078,31 @@ def get_employee_engagement_work_board(
document, checklist, AQMM and lock controls remain the source of truth.
"""
today = date.today()
# Cross-view AQMM self-heal: an engagement that has already passed the
# engagement-level AQMM acceptance must never continue to show the four
# duplicated setup rows as pending in the Staff work board. Reconcile the
# persisted execution rows before the board queries them. The synchroniser
# is deliberately limited to untouched acceptance/team/independence/KYC
# setup rows and does not modify normal execution history, evidence or rework.
subscription_stmt = select(ClientServiceSubscription).where(
ClientServiceSubscription.id == int(engagement_id),
ClientServiceSubscription.tenant_id == int(scope.tenant_id),
)
if scope.branch_id is not None:
subscription_stmt = subscription_stmt.where(
ClientServiceSubscription.branch_id == int(scope.branch_id)
)
subscription_for_sync = db.execute(subscription_stmt).scalar_one_or_none()
if subscription_for_sync is not None:
repaired = synchronise_approved_engagement_acceptance_tasks(
db,
subscription=subscription_for_sync,
actor_user_id=int(scope.own_user_id),
)
if repaired:
db.commit()
assigned_stmt = _employee_work_task_query(
db, scope, assigned_only=True, financial_year=financial_year
).where(ClientServiceTaskInstance.subscription_id == engagement_id)
+14 -1
View File
@@ -17,7 +17,7 @@ from app.modules.employees.service import (
_engagement_team,
_weighted_progress,
)
from app.modules.services.execution import CLOSED_TASK_STATUSES
from app.modules.services.execution import CLOSED_TASK_STATUSES, synchronise_approved_engagement_acceptance_tasks
from app.modules.services.models import ClientServiceSubscription, ClientServiceTaskInstance, ServiceCatalogue, ServiceTaskComment
MANAGER_ROLES = {"Manager", "Branch Manager", "System Admin", "Firm Admin", "Partner"}
@@ -599,6 +599,19 @@ def get_manager_review_workspace(
if not tasks:
return None
subscription_for_sync = getattr(tasks[0], "subscription", None)
if subscription_for_sync is not None:
repaired_setup_rows = synchronise_approved_engagement_acceptance_tasks(
db,
subscription=subscription_for_sync,
actor_user_id=int(current_user.id),
)
if repaired_setup_rows:
db.commit()
tasks = list(db.execute(
stmt.order_by(ClientServiceTaskInstance.sequence_no.asc(), ClientServiceTaskInstance.id.asc())
).scalars().all())
task_rows = [_manager_review_task_row(task) for task in tasks]
reviewable = [row for row in task_rows if row["review_state"] in {"pending_review", "reviewed", "rework"}]
pending = [row for row in reviewable if row["review_state"] == "pending_review"]
+20
View File
@@ -18,6 +18,7 @@ from app.modules.services.execution import (
CLOSED_TASK_STATUSES,
aqmm_task_summary_for_subscription,
closure_readiness_for_subscription,
synchronise_approved_engagement_acceptance_tasks,
)
from app.modules.services.models import (
ClientServiceSubscription,
@@ -571,6 +572,17 @@ def _partner_review_queue_rows(db: Session, request, current_user, *, limit: int
ClientServiceSubscription.review_partner_user_id == current_user.id,
))
subscriptions = list(db.execute(stmt.order_by(ClientServiceSubscription.current_due_date.is_(None), ClientServiceSubscription.current_due_date.asc(), ClientServiceSubscription.id.desc()).limit(limit)).scalars().all())
repaired_setup_rows = 0
for sub in subscriptions:
repaired_setup_rows += synchronise_approved_engagement_acceptance_tasks(
db,
subscription=sub,
actor_user_id=int(current_user.id),
)
if repaired_setup_rows:
db.commit()
rows: list[dict[str, Any]] = []
for sub in subscriptions:
task_stmt = select(ClientServiceTaskInstance).where(
@@ -638,6 +650,14 @@ def get_partner_review_workspace(db: Session, request, current_user, *, subscrip
}:
return None
repaired_setup_rows = synchronise_approved_engagement_acceptance_tasks(
db,
subscription=subscription,
actor_user_id=int(current_user.id),
)
if repaired_setup_rows:
db.commit()
task_stmt = (
select(ClientServiceTaskInstance)
.options(
+29 -1
View File
@@ -18,7 +18,12 @@ from app.modules.core.rbac.deps import get_user_permissions, get_user_roles
from app.modules.documents.models import EngagementDocument
from app.modules.clients.models import Client, ClientBranch, ClientBusinessUnit
from app.modules.registrations.models import ClientRegistration, RegistrationType
from app.modules.services.execution import CLOSED_TASK_STATUSES, TASK_PRIORITIES, TASK_STATUSES
from app.modules.services.execution import (
CLOSED_TASK_STATUSES,
TASK_PRIORITIES,
TASK_STATUSES,
synchronise_approved_engagement_acceptance_tasks,
)
from app.modules.services.engagement_resources import build_engagement_resource_context
from app.modules.services.models import (
ClientServiceSubscription,
@@ -408,6 +413,21 @@ def build_partner_payload(
)
option_stmt = _subscription_scope_filter(option_stmt, tenant_id, branch_id, current_user, roles, financial_year=None)
option_engagements = db.execute(option_stmt).scalars().all()
# Keep the Review Board in step with the engagement-level AQMM workflow.
# Older generated task rows can retain their original AQMM gate flags even
# after acceptance is approved; reconcile only those duplicated setup rows
# before task buckets/counts are built.
repaired_setup_rows = 0
for subscription in option_engagements:
repaired_setup_rows += synchronise_approved_engagement_acceptance_tasks(
db,
subscription=subscription,
actor_user_id=int(current_user.id),
)
if repaired_setup_rows:
db.commit()
financial_year_options = sorted({(row.financial_year or "").strip() for row in option_engagements if (row.financial_year or "").strip()}, reverse=True)
period_options = sorted({(row.period_label or "").strip() for row in option_engagements if (row.period_label or "").strip()})
service_map = {}
@@ -697,6 +717,14 @@ def partner_engagement_detail(request: Request, engagement_id: int):
if not engagement:
return _redirect_denied()
repaired_setup_rows = synchronise_approved_engagement_acceptance_tasks(
db,
subscription=engagement,
actor_user_id=int(current_user.id),
)
if repaired_setup_rows:
db.commit()
task_stmt = select(ClientServiceTaskInstance).options(
selectinload(ClientServiceTaskInstance.client),
selectinload(ClientServiceTaskInstance.catalogue),