column_facet.py 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. """列头漏斗可选值(去重 facet)公共拼装。"""
  2. from __future__ import annotations
  3. from typing import Any, Callable, Dict, List, Optional
  4. from sqlalchemy import Column, func
  5. from sqlalchemy.orm import Query, Session
  6. def list_column_facet_values(
  7. db: Session,
  8. model: Any,
  9. column: Column,
  10. *,
  11. tenant_no: str,
  12. keyword: Optional[str] = None,
  13. limit: int = 500,
  14. apply_scope: Optional[Callable[[Query], Query]] = None,
  15. extra_filters: Optional[List[Any]] = None,
  16. ) -> List[Dict[str, Any]]:
  17. """对业务表某列做去重可选值查询。
  18. 约束:tenant_no + del_flag=0;空值剔除;按列值升序;limit 上限 500。
  19. apply_scope:可选,注入数据权限(如 apply_crm_create_by_scope 包装后的 q 变换)。
  20. extra_filters:额外 SQLAlchemy 条件(如 status=='on'、公海 view_mode)。
  21. """
  22. lim = min(max(1, int(limit or 500)), 500)
  23. q = db.query(column.label("value"), func.count(model.id).label("cnt")).filter(
  24. model.tenant_no == tenant_no,
  25. model.del_flag == 0,
  26. column.isnot(None),
  27. column != "",
  28. )
  29. if extra_filters:
  30. for expr in extra_filters:
  31. if expr is not None:
  32. q = q.filter(expr)
  33. if apply_scope is not None:
  34. q = apply_scope(q)
  35. kw = (keyword or "").strip()
  36. if kw:
  37. q = q.filter(column.like(f"%{kw}%"))
  38. rows = q.group_by(column).order_by(column.asc()).limit(lim).all()
  39. out: List[Dict[str, Any]] = []
  40. for row in rows:
  41. value = str(row.value).strip() if row.value is not None else ""
  42. if not value:
  43. continue
  44. out.append({"value": value, "label": value, "count": int(row.cnt or 0)})
  45. return out