Add compact searchable consultant client list

This commit is contained in:
A R R R Associates
2026-07-31 12:22:24 +05:30
parent d791670003
commit 07668318aa
4 changed files with 336 additions and 34 deletions
+116
View File
@@ -326,6 +326,122 @@ def list_client_links_for_consultant(db: Session, *, consultant_id: int) -> list
).scalars().all()
def consultant_linked_clients_page(
db: Session,
*,
consultant: ConsultantProfile,
q: str = "",
client_group_id: int | None = None,
status: str = "active",
page: int = 1,
per_page: int = 25,
sort_by: str = "client_name",
sort_order: str = "asc",
) -> dict:
"""Return a compact, searchable and paginated list of linked firm clients.
Link permission columns remain unchanged and continue to govern the existing
service, due-date, communication and document workflows. They are deliberately
not exposed in the client-list UI.
"""
q = (q or "").strip()
status = (status or "").strip().lower()
per_page = min(max(int(per_page or 25), 1), 100)
page = max(int(page or 1), 1)
stmt = (
select(ClientConsultantLink, Client, ClientGroup)
.join(Client, Client.id == ClientConsultantLink.client_id)
.outerjoin(ClientGroup, ClientGroup.id == Client.client_group_id)
.where(
ClientConsultantLink.tenant_id == consultant.tenant_id,
ClientConsultantLink.consultant_id == consultant.id,
ClientConsultantLink.is_active.is_(True),
Client.tenant_id == consultant.tenant_id,
Client.is_archived.is_(False),
)
)
if status:
stmt = stmt.where(Client.status == status)
if client_group_id:
stmt = stmt.where(Client.client_group_id == int(client_group_id))
if q:
like = f"%{q}%"
stmt = stmt.where(
or_(
Client.client_code.ilike(like),
Client.client_name.ilike(like),
Client.trade_name.ilike(like),
Client.pan.ilike(like),
Client.gstin.ilike(like),
ClientGroup.group_name.ilike(like),
ClientGroup.group_code.ilike(like),
)
)
total = int(db.execute(select(func.count()).select_from(stmt.subquery())).scalar_one() or 0)
pages = max(ceil(total / per_page), 1)
page = min(page, pages)
sort_columns = {
"client_code": Client.client_code,
"client_name": Client.client_name,
"pan": Client.pan,
"client_group": ClientGroup.group_name,
"status": Client.status,
}
sort_column = sort_columns.get(sort_by, Client.client_name)
ordering = sort_column.desc() if (sort_order or "asc").lower() == "desc" else sort_column.asc()
rows = []
result = db.execute(
stmt.order_by(ordering, Client.id.asc())
.offset((page - 1) * per_page)
.limit(per_page)
).all()
for link, client, group in result:
rows.append({
"link": link,
"client": client,
"client_group_id": getattr(group, "id", None),
"client_group_code": getattr(group, "group_code", None),
"client_group_name": getattr(group, "group_name", None),
"relationship_label": (link.relationship_type or "accounts_consultant").replace("_", " ").title(),
})
groups_stmt = (
select(ClientGroup.id, ClientGroup.group_code, ClientGroup.group_name)
.join(Client, Client.client_group_id == ClientGroup.id)
.join(ClientConsultantLink, ClientConsultantLink.client_id == Client.id)
.where(
ClientConsultantLink.tenant_id == consultant.tenant_id,
ClientConsultantLink.consultant_id == consultant.id,
ClientConsultantLink.is_active.is_(True),
Client.tenant_id == consultant.tenant_id,
Client.is_archived.is_(False),
ClientGroup.is_active.is_(True),
)
.distinct()
.order_by(ClientGroup.group_name.asc())
)
groups = [
{"id": int(group_id), "code": code, "name": name}
for group_id, code, name in db.execute(groups_stmt).all()
]
return {
"rows": rows,
"groups": groups,
"meta": {"total": total, "page": page, "per_page": per_page, "pages": pages},
"filters": {
"q": q,
"client_group_id": client_group_id,
"status": status,
"sort_by": sort_by if sort_by in sort_columns else "client_name",
"sort_order": "desc" if (sort_order or "asc").lower() == "desc" else "asc",
},
}
def link_client_to_consultant(
db: Session,
*,