Add phase 1 client consultant referral and linkage

This commit is contained in:
A R R R Associates
2026-07-22 23:45:05 +05:30
parent 02a549bd05
commit 8f51d16c7d
10 changed files with 290 additions and 5 deletions
+13
View File
@@ -162,6 +162,19 @@ class ClientConsultantLink(CommonBase):
can_view_services: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
can_view_due_dates: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
can_view_communications: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
can_view_engagements: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
can_view_task_status: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
can_view_assignee: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
can_view_document_requests: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
can_upload_documents: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
can_reply_to_clarifications: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
can_view_filing_details: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
can_view_final_documents: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
can_view_permanent_documents: Mapped[bool] = mapped_column(Boolean, nullable=False, default=False)
can_receive_notifications: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
can_act_for_client: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True)
effective_from: Mapped[date | None] = mapped_column(Date, nullable=True)
effective_to: Mapped[date | None] = mapped_column(Date, nullable=True)
is_active: Mapped[bool] = mapped_column(Boolean, nullable=False, default=True, index=True)
remarks: Mapped[str | None] = mapped_column(Text, nullable=True)
+72
View File
@@ -1388,3 +1388,75 @@ def reject_managed_client_conversion(
managed_client.conversion_firm_notes = normalise_text(firm_notes)
managed_client.updated_by_user_id = user_id
return managed_client
def get_primary_client_consultant_link(db: Session, *, tenant_id: int, client_id: int) -> ClientConsultantLink | None:
return db.execute(
select(ClientConsultantLink)
.where(
ClientConsultantLink.tenant_id == tenant_id,
ClientConsultantLink.client_id == client_id,
ClientConsultantLink.is_primary.is_(True),
ClientConsultantLink.is_active.is_(True),
)
.order_by(ClientConsultantLink.id.asc())
).scalars().first()
def sync_primary_client_consultant_link(
db: Session, *, client: Client, consultant_id: int | None, actor_user_id: int
) -> ClientConsultantLink | None:
"""Synchronise the client's unrestricted primary consultant link without deleting history."""
links = db.execute(
select(ClientConsultantLink).where(
ClientConsultantLink.tenant_id == client.tenant_id,
ClientConsultantLink.client_id == client.id,
)
).scalars().all()
selected = None
for link in links:
if consultant_id and int(link.consultant_id) == int(consultant_id) and link.service_catalogue_id is None:
selected = link
elif link.is_primary:
link.is_primary = False
link.updated_by_user_id = actor_user_id
if consultant_id is None:
db.flush()
return None
consultant = get_consultant(db, tenant_id=int(client.tenant_id), consultant_id=int(consultant_id))
if not consultant or not consultant.is_active:
raise ValueError("Selected primary consultant is not active in this firm.")
if selected is None:
selected = ClientConsultantLink(
tenant_id=client.tenant_id, branch_id=client.branch_id, client_id=client.id,
consultant_id=consultant.id, service_catalogue_id=None,
relationship_type="accounts_consultant", is_primary=True, is_active=True,
can_view_client=True, can_view_services=True, can_view_due_dates=True,
can_view_communications=True, can_view_engagements=True, can_view_task_status=True,
can_view_assignee=True, can_view_document_requests=True, can_upload_documents=True,
can_reply_to_clarifications=True, can_view_filing_details=True,
can_view_final_documents=True, can_view_permanent_documents=False,
can_receive_notifications=True, can_act_for_client=True,
effective_from=getattr(client, "referral_date", None) or date.today(),
created_by_user_id=actor_user_id, updated_by_user_id=actor_user_id,
)
db.add(selected)
else:
selected.branch_id = client.branch_id
selected.is_primary = True
selected.is_active = True
selected.updated_by_user_id = actor_user_id
db.flush()
return selected
def get_client_consultant_summary(db: Session, *, tenant_id: int, client_id: int) -> dict:
primary = get_primary_client_consultant_link(db, tenant_id=tenant_id, client_id=client_id)
referred_id = db.execute(select(Client.referred_by_consultant_id).where(Client.id == client_id)).scalar_one_or_none()
ids = {int(x) for x in (getattr(primary, "consultant_id", None), referred_id) if x}
profiles = db.execute(select(ConsultantProfile).where(ConsultantProfile.id.in_(ids))).scalars().all() if ids else []
by_id = {int(x.id): x for x in profiles}
return {
"primary": by_id.get(int(primary.consultant_id)) if primary else None,
"referred_by": by_id.get(int(referred_id)) if referred_id else None,
}