Files
arrr-erp/app/modules/clients/auditor_service.py
T
2026-06-20 15:01:44 +05:30

121 lines
4.0 KiB
Python

from __future__ import annotations
from sqlalchemy import select
from sqlalchemy.orm import Session
from app.modules.core.iam.models import User
from app.modules.core.iam.profile_service import profile_photo_url
from app.modules.core.tenancy.models import Branch, Tenant
def _initials(name: str | None, email: str | None = None) -> str:
source = (name or email or "Auditor").strip()
parts = [p for p in source.replace("@", " ").replace(".", " ").split() if p]
if not parts:
return "AU"
if len(parts) == 1:
return parts[0][:2].upper()
return (parts[0][:1] + parts[-1][:1]).upper()
def _contact_card_from_user(
*,
user: User | None,
tenant_name: str | None,
branch_name: str | None,
source_label: str,
) -> dict:
if not user:
return {
"available": False,
"name": "Firm team",
"designation": "Audit support team",
"qualification": None,
"email": None,
"mobile": None,
"photo_url": None,
"initials": "FT",
"firm_name": tenant_name,
"branch_name": branch_name,
"source_label": source_label,
}
name = getattr(user, "full_name", None) or getattr(user, "email", None) or "Firm team"
designation = getattr(user, "designation", None) or source_label or "Auditor"
return {
"available": True,
"name": name,
"designation": designation,
"qualification": getattr(user, "qualification", None),
"email": getattr(user, "email", None),
"mobile": getattr(user, "mobile", None),
"photo_url": profile_photo_url(user),
"initials": _initials(name, getattr(user, "email", None)),
"firm_name": tenant_name,
"branch_name": branch_name,
"source_label": source_label,
}
def build_client_auditor_card(db: Session, client_row: dict | None) -> dict:
"""Return a client-facing contact card for the assigned auditor/partner.
Priority:
1. Client assigned partner (`partner_id`).
2. Default review partner, if no assigned partner exists.
3. Firm team fallback using tenant/branch names.
This reuses Phase 7Q.3 user profile fields and does not create new tables.
"""
if not client_row:
return _contact_card_from_user(
user=None,
tenant_name=None,
branch_name=None,
source_label="Firm team",
)
tenant_name = client_row.get("tenant_name")
branch_name = client_row.get("branch_name")
tenant_id = client_row.get("tenant_id")
branch_id = client_row.get("branch_id")
partner_id = client_row.get("partner_id") or client_row.get("assoc_partner_user_id")
review_partner_id = client_row.get("default_review_partner_user_id")
target_user_id = partner_id or review_partner_id
source_label = "Assigned Auditor" if partner_id else "Review Partner"
if not target_user_id:
return _contact_card_from_user(
user=None,
tenant_name=tenant_name,
branch_name=branch_name,
source_label="Firm team",
)
stmt = (
select(User, Tenant.name.label("tenant_name"), Branch.name.label("branch_name"))
.join(Tenant, Tenant.id == User.tenant_id, isouter=True)
.join(Branch, Branch.id == User.branch_id, isouter=True)
.where(User.id == int(target_user_id), User.deleted_at.is_(None))
)
if tenant_id:
stmt = stmt.where(User.tenant_id == int(tenant_id))
result = db.execute(stmt).first()
if not result:
return _contact_card_from_user(
user=None,
tenant_name=tenant_name,
branch_name=branch_name,
source_label="Firm team",
)
user, resolved_tenant_name, resolved_branch_name = result
return _contact_card_from_user(
user=user,
tenant_name=resolved_tenant_name or tenant_name,
branch_name=resolved_branch_name or branch_name,
source_label=source_label,
)