facet_context.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. """CRM 列头 facet:从 column_filter_kwargs 中清除当前列自身条件。"""
  2. from __future__ import annotations
  3. import re
  4. from typing import Any, Dict, Mapping, MutableMapping, Optional, Sequence
  5. # field(prop/API) → column_filter_kwargs 中应清空的 snake 键
  6. CRM_FACET_FIELD_KWARG_KEYS: Dict[str, Sequence[str]] = {
  7. # customer
  8. "customerNo": ("customer_no", "customer_no_in"),
  9. "customerName": ("customer_name", "customer_name_in"),
  10. "shortName": ("short_name", "short_name_in"),
  11. # product
  12. "productNo": ("product_no", "product_no_in"),
  13. "productName": ("product_name", "product_name_in"),
  14. "categoryName": ("category_name", "category_name_in"),
  15. "brands": ("brands", "brands_in", "brand", "brand_in"),
  16. "aliases": ("aliases", "aliases_in", "alias", "alias_in"),
  17. "model": ("model", "model_in"),
  18. # clue
  19. "clueName": ("clue_name", "clue_name_in"),
  20. "company": ("company", "company_in"),
  21. # opportunity
  22. "opportunityNo": ("opportunity_no", "opportunity_no_in"),
  23. "opportunityName": ("opportunity_name", "opportunity_name_in"),
  24. # quote / contract share customerName
  25. "quoteNo": ("quote_no", "quote_no_in"),
  26. "contractNo": ("contract_no", "contract_no_in"),
  27. "contractName": ("contract_name", "contract_name_in"),
  28. "templateNo": ("template_no", "template_no_in"),
  29. "templateName": ("template_name", "template_name_in"),
  30. # supplier / price letter
  31. "supplierCode": ("supplier_code", "supplier_code_in"),
  32. "supplierName": ("supplier_name", "supplier_name_in"),
  33. }
  34. _META_KEYS = frozenset(
  35. {
  36. "field",
  37. "keyword",
  38. "limit",
  39. "page",
  40. "pageSize",
  41. "page_size",
  42. "pageNum",
  43. "page_num",
  44. "ids",
  45. "columns",
  46. "sortField",
  47. "sort_field",
  48. "sortOrder",
  49. "sort_order",
  50. }
  51. )
  52. def _camel_to_snake(name: str) -> str:
  53. s1 = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", name)
  54. return re.sub("([a-z0-9])([A-Z])", r"\1_\2", s1).lower()
  55. def clear_facet_field_kwargs(
  56. kwargs: Mapping[str, object],
  57. field: str,
  58. *,
  59. extra_keys: Optional[Sequence[str]] = None,
  60. ) -> Dict[str, object]:
  61. """返回清除当前 facet 列相关键后的 kwargs 副本(值置 None)。"""
  62. out: Dict[str, object] = dict(kwargs)
  63. keys = list(CRM_FACET_FIELD_KWARG_KEYS.get(str(field or "").strip(), ()))
  64. if extra_keys:
  65. keys.extend(extra_keys)
  66. for key in keys:
  67. if key in out:
  68. out[key] = None
  69. return out
  70. def strip_crm_facet_body_params(
  71. params: MutableMapping[str, object], field: str
  72. ) -> Dict[str, object]:
  73. """从原始 camelCase body dump 中去掉本列键与元数据(兼容无 mixin 路径)。"""
  74. from app.services.pl.facet_context import strip_simple_facet_self_params
  75. return strip_simple_facet_self_params(params, field)
  76. def facet_filter_kwargs_from_body(body: Any, field: str) -> Dict[str, object]:
  77. """从 Facet Body(含 extra=allow)提取 snake_case 列筛 kwargs,并清除当前列。"""
  78. dumped = body.model_dump(
  79. by_alias=False,
  80. exclude_none=False,
  81. exclude={"field", "keyword", "limit"},
  82. )
  83. out: Dict[str, object] = {}
  84. for key, value in dumped.items():
  85. if key in _META_KEYS or value is None or value == "":
  86. continue
  87. out[key] = value
  88. extra = getattr(body, "model_extra", None) or {}
  89. for key, value in extra.items():
  90. if key in _META_KEYS or value is None or value == "":
  91. continue
  92. snake = _camel_to_snake(key) if any(c.isupper() for c in key) else key
  93. if snake in _META_KEYS:
  94. continue
  95. out[snake] = value
  96. return clear_facet_field_kwargs(out, field)