diff --git a/lawrisk_v2_service.py b/lawrisk_v2_service.py index 2153db1..2db128c 100644 --- a/lawrisk_v2_service.py +++ b/lawrisk_v2_service.py @@ -14,20 +14,22 @@ def _compose_prompt(payload: Dict[str, Any]) -> str: """Build a natural-language prompt snippet from structured payload.""" region = payload.get("region", {}) theme = payload.get("theme", {}) - scopes = payload.get("business_scopes", []) permits = payload.get("permits", []) lines: List[str] = [] lines.append(f"地区:{region.get('name', '')}") lines.append(f"主题事项:{theme.get('name', '')}") - if scopes: - scope_text = ";".join(scope.get("description", "") for scope in scopes if scope.get("description")) - if scope_text: - lines.append(f"涉及经营范围:{scope_text}") for permit in permits: pname = permit.get("name", "") lines.append(f"许可事项:{pname}") + permit_scopes = permit.get("business_scopes", []) + if permit_scopes: + scope_text = ";".join( + scope.get("description", "") for scope in permit_scopes if scope.get("description") + ) + if scope_text: + lines.append(f" 经营范围:{scope_text}") risks = permit.get("risks", []) for idx, risk in enumerate(risks, start=1): detail_parts = [] diff --git a/licensing_repo.py b/licensing_repo.py index 7572c8b..ff2a6d5 100644 --- a/licensing_repo.py +++ b/licensing_repo.py @@ -1,7 +1,7 @@ from __future__ import annotations import os -from typing import Dict, List, Tuple +from typing import Dict, List import pg8000.dbapi as pg @@ -71,6 +71,39 @@ def load_business_scopes(region_id: str) -> List[Dict[str, str]]: return scopes +def _load_permit_scopes_for_region( + conn: pg.Connection, region_id: str, permit_ids: List[str] +) -> Dict[str, List[Dict[str, str]]]: + """Return mapping of permit_id -> business scopes for that permit within region.""" + scope_map: Dict[str, List[Dict[str, str]]] = {pid: [] for pid in permit_ids} + if not permit_ids: + return scope_map + + sql = """ + SELECT rps.permit_id, bs.id, bs.description + FROM region_permit_scopes rps + JOIN business_scopes bs ON bs.id = rps.scope_id + WHERE rps.region_id = %s + ORDER BY rps.permit_id, bs.description + """ + cur = conn.cursor() + try: + cur.execute(sql, (region_id,)) + except pg.ProgrammingError as exc: + # 42P01 => undefined_table; allow fallback when migration not yet applied. + sqlstate = getattr(exc, "sqlstate", "") + if sqlstate == "42P01": + return scope_map + raise + + for permit_id, scope_id, description in cur.fetchall(): + pid = str(permit_id) + if pid not in scope_map: + continue + scope_map[pid].append({"id": str(scope_id), "description": str(description)}) + return scope_map + + def load_permits_and_risks(region_id: str, theme_id: str) -> List[Dict[str, object]]: """Return permits with attached risk entries for a region-theme pair.""" sql = """ @@ -103,20 +136,25 @@ def load_permits_and_risks(region_id: str, theme_id: str) -> List[Dict[str, obje { "id": pid, "name": str(permit_name), + "business_scopes": [], "risks": [], }, ) - if risk_id is None: - continue - entry["risks"].append( - { - "id": str(risk_id), - "risk_content": risk_content or "", - "legal_basis": legal_basis or "", - "document_no": document_no or "", - "summary": summary or "", - } - ) + if risk_id is not None: + entry["risks"].append( + { + "id": str(risk_id), + "risk_content": risk_content or "", + "legal_basis": legal_basis or "", + "document_no": document_no or "", + "summary": summary or "", + } + ) + + permit_ids = list(permits.keys()) + scope_map = _load_permit_scopes_for_region(conn, region_id, permit_ids) + for pid in permit_ids: + permits[pid]["business_scopes"] = scope_map.get(pid, []) return list(permits.values()) @@ -138,12 +176,9 @@ def load_theme_payload(region_id: str, theme_id: str) -> Dict[str, object]: raise ValueError("Region/theme combination not found") region_uuid, region_name, theme_uuid, theme_name = row - scopes = load_business_scopes(region_id) permits = load_permits_and_risks(region_id, theme_id) return { "region": {"id": str(region_uuid), "name": str(region_name)}, "theme": {"id": str(theme_uuid), "name": str(theme_name)}, - "business_scopes": scopes, "permits": permits, } -