Add phase 3 consultant task execution workflow

This commit is contained in:
A R R R Associates
2026-07-23 11:37:04 +05:30
parent e9db81b32f
commit 0f7d6f4396
9 changed files with 365 additions and 2 deletions
+53 -1
View File
@@ -1,7 +1,7 @@
from __future__ import annotations
from collections import OrderedDict
from datetime import date, timedelta
from datetime import date, datetime, timedelta, timezone
from typing import Any
from sqlalchemy import or_, select
@@ -171,3 +171,55 @@ def get_consultant_document_centre(db: Session, *, consultant: ConsultantProfile
term=f"%{q.strip()}%"; stmt=stmt.where(or_(PermanentClientDocument.title.ilike(term),PermanentClientDocument.category.ilike(term),PermanentClientDocument.document_code.ilike(term)))
permanent_documents=db.execute(stmt.order_by(PermanentClientDocument.created_at_utc.desc()).limit(200)).scalars().all()
return {"engagement_documents":engagement_documents,"permanent_documents":permanent_documents,"total":len(engagement_documents)+len(permanent_documents)}
def consultant_can_execute_task(*, consultant: ConsultantProfile, task: ClientServiceTaskInstance) -> bool:
return bool(task.execution_mode == "consultant" and task.assigned_consultant_id == consultant.id and task.is_active and not task.is_locked)
def update_consultant_assignment(db: Session, *, consultant: ConsultantProfile, task: ClientServiceTaskInstance, action: str, note: str, user_id: int) -> tuple[bool, str | None]:
if not consultant_can_execute_task(consultant=consultant, task=task):
return False, "This task is not assigned to your consultant profile."
action = (action or "").strip().lower()
note = (note or "").strip()
current = (task.consultant_assignment_status or "not_applicable").lower()
now = datetime.now(timezone.utc)
message = None
if action == "accept" and current == "offered":
task.consultant_assignment_status = "accepted"
task.consultant_accepted_at_utc = now
task.consultant_declined_at_utc = None
task.consultant_decline_reason = None
task.status = "pending"
message = "Consultant accepted the assignment."
elif action == "decline" and current == "offered":
if not note:
return False, "Decline reason is required."
task.consultant_assignment_status = "declined"
task.consultant_declined_at_utc = now
task.consultant_decline_reason = note
task.status = "pending"
message = f"Consultant declined the assignment: {note}"
elif action == "start" and current in {"accepted", "rework_required"}:
task.consultant_assignment_status = "in_progress"
task.consultant_started_at_utc = task.consultant_started_at_utc or now
task.status = "in_progress"
if current == "rework_required":
task.rework_status = "in_progress"
message = "Consultant started work on the assignment."
elif action == "submit" and current in {"accepted", "in_progress", "rework_required"}:
if not note:
return False, "Submission note is required."
task.consultant_assignment_status = "submitted"
task.consultant_submitted_at_utc = now
task.consultant_submission_note = note
task.status = "pending_review"
if task.rework_status in {"requested", "in_progress"}:
task.rework_status = "resolved"
task.rework_resolved_at_utc = now
message = f"Consultant submitted the assignment for firm review: {note}"
else:
return False, "This action is not allowed for the current assignment status."
task.updated_by_user_id = user_id
db.add(ServiceTaskComment(tenant_id=task.tenant_id, branch_id=task.branch_id, subscription_id=task.subscription_id, task_instance_id=task.id, comment_type="consultant_execution", visibility="consultant", message=message, created_by_user_id=user_id))
return True, None