"""Podmienia POST /api/projects/match-program na rule-based MatcherAI (bez LLM domyślnie).""" import logging logger = logging.getLogger(__name__) def apply_projects_match_patch() -> None: try: import endpoints.projects as projects_mod from fastapi import Body, Depends from endpoints.projects import MatchProgramRequest, get_db, verify_token except ImportError as e: logger.warning("[ProjectsMatchPatch] skip: %s", e) return if getattr(projects_mod, "_match_program_patched", False): return router = projects_mod.router def _is_match_program_route(route) -> bool: path = (getattr(route, "path", "") or "").rstrip("/") if path not in ("/match-program", "/api/projects/match-program"): return False methods = getattr(route, "methods", set()) or set() return "POST" in methods removed = 0 for route in list(router.routes): if _is_match_program_route(route): router.routes.remove(route) removed += 1 if removed: logger.info("[ProjectsMatchPatch] usunięto %s legacy POST /match-program", removed) @router.post("/match-program") async def match_program_patched( payload: MatchProgramRequest = Body(...), token_data: dict = Depends(verify_token), db=Depends(get_db), ): try: from core.match import match_program_service user_answers = None if payload.user_answers: user_answers = [ua.model_dump() for ua in payload.user_answers] result = await match_program_service.run_match_program( db, nip=payload.nip, description=payload.description or "", user_answers=user_answers, company_type=payload.company_type, company_size=payload.company_size, voivodeship=payload.voivodeship, innovation_type=payload.innovation_type, ) return { "programs": result.get("programs", []), "clarifying_questions": result.get("clarifying_questions", []), "data_gaps": result.get("data_gaps", []), "status": result.get("status", "ok"), "match_mode": result.get("match_mode"), "needs_more_info": result.get("needs_more_info", False), "company_profile": result.get("company_profile"), "catalog_count": result.get("catalog_count", 0), "message": result.get("message"), } except Exception as e: logger.error("Error in match_program: %s", e, exc_info=True) return { "status": "error", "programs": [], "clarifying_questions": [ "Wystąpił błąd analizy dopasowań. Spróbuj ponownie lub uzupełnij NIP i opis projektu.", "Podaj kod PKD i województwo realizacji projektu — umożliwi dopasowanie bez AI.", ], "data_gaps": [], "error": str(e)[:200], } projects_mod._match_program_patched = True logger.info("[ProjectsMatchPatch] POST /match-program → rule-based MatcherAI aktywne.")