grantforge-api / backend /endpoints /projects_match_patch.py
GrantForge Bot
Deploy sha-9a5957fcdef15b7e2623f8b147cda6026475aee0 — source build (no GHCR)
3a3734f
Raw
History Blame Contribute Delete
3.33 kB
"""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.")