demand_grade_videos.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. """Resolve demand_video_expansion → videos + expansion points for the web UI."""
  2. from __future__ import annotations
  3. import json
  4. from typing import Any
  5. from supply_infra.db.repositories.demand_grade_repo import DemandGradeRepository
  6. from supply_infra.db.repositories.demand_video_expansion_repo import (
  7. DemandVideoExpansionRepository,
  8. DemandVideoExpansionRunRepository,
  9. )
  10. from supply_infra.db.repositories.multi_demand_video_detail_repo import (
  11. MultiDemandVideoDetailRepository,
  12. )
  13. from supply_infra.db.session import get_session
  14. def _parse_json_list(raw: str | None) -> list[Any]:
  15. if not raw:
  16. return []
  17. try:
  18. parsed = json.loads(raw)
  19. except json.JSONDecodeError:
  20. return []
  21. return parsed if isinstance(parsed, list) else []
  22. def list_videos_for_demand_grade(demand_grade_id: int) -> dict[str, Any] | None:
  23. """
  24. 按 demand_grade.id 返回该需求在对应 biz_dt 下的拓展视频与选题结果。
  25. 数据来源:
  26. - demand_video_expansion_run:判断是否已完成拓展(含零结果)
  27. - demand_video_expansion:真实视频实例与拓展点位
  28. """
  29. with get_session() as session:
  30. grade = DemandGradeRepository(session).get_by_id(demand_grade_id)
  31. if grade is None:
  32. return None
  33. biz_dt = str(grade.biz_dt)
  34. run = DemandVideoExpansionRunRepository(session).get_by_demand_grade(
  35. biz_dt, demand_grade_id
  36. )
  37. expansions = DemandVideoExpansionRepository(session).list_by_demand_grade(
  38. biz_dt, demand_grade_id
  39. )
  40. vids: list[str] = []
  41. seen_vids: set[str] = set()
  42. points_by_vid: dict[str, list[dict[str, Any]]] = {}
  43. for row in expansions:
  44. vid = str(row.video_id).strip()
  45. if not vid:
  46. continue
  47. if vid not in seen_vids:
  48. seen_vids.add(vid)
  49. vids.append(vid)
  50. points_by_vid.setdefault(vid, []).append(
  51. {
  52. "expanded_text": row.expanded_text,
  53. "point_type": row.point_type,
  54. "point_desc": row.point_desc,
  55. "reason": row.reason,
  56. }
  57. )
  58. details = MultiDemandVideoDetailRepository(session).list_by_vids(vids)
  59. videos: list[dict[str, Any]] = []
  60. for vid in vids:
  61. row = details.get(vid)
  62. videos.append(
  63. {
  64. "vid": vid,
  65. "title": row.title if row else None,
  66. "expansion_points": points_by_vid.get(vid, []),
  67. }
  68. )
  69. expansion_status: str | None = None
  70. expansion_saved_count = 0
  71. if run is not None:
  72. expansion_status = str(run.status)
  73. expansion_saved_count = int(run.saved_count or 0)
  74. return {
  75. "demand_grade_id": grade.id,
  76. "demand_name": grade.demand_name,
  77. "biz_dt": biz_dt,
  78. "category_ids": [int(c) for c in _parse_json_list(grade.category_ids)],
  79. "grade": grade.grade,
  80. "strategies": _parse_json_list(grade.strategies),
  81. "expansion_status": expansion_status,
  82. "expansion_saved_count": expansion_saved_count,
  83. "videos": videos,
  84. }