"""카드 매핑 API (card-update / card-search, tenant 스코프). PoC: action_id ↔ card_id 매핑을 learning.tenant_action_cards 에 둔다(config 기본 + DB override). 카드 스크립트 본문은 ScriptRepository(tenants//resources)가 담당 — 여기선 매핑만. """ from typing import Optional from fastapi import APIRouter, Depends from pydantic import BaseModel from common.enums import ErrorType from negotiation.qtable.infra.repository.learning_repository import LearningRepository from router.deps import get_tenant_engine from tenancy.registry import TenantEngine router = APIRouter(prefix="/v1", tags=["Card"], responses={404: {"description": "Not found"}}) async def _merged_mapping(engine: TenantEngine) -> dict: """config 기본 매핑 위에 DB override 를 얹은 action→card 최종 매핑.""" mapping = {int(a): c for a, c in engine.config.action_mapping.action_to_card.items()} overrides = await LearningRepository(engine.company_id).get_action_cards() for o in overrides: mapping[o["action_id"]] = o["card_id"] return mapping class CardUpdateReq(BaseModel): action_id: int card_id: str @router.post("/card-update", summary="카드 매핑 갱신(action→card)") async def card_update(req: CardUpdateReq, engine: TenantEngine = Depends(get_tenant_engine)): if not (0 <= req.action_id < engine.action_space_size): return {"success": False, "desc": "action_id out of range", "action_space_size": engine.action_space_size} err = await LearningRepository(engine.company_id).upsert_action_card(req.action_id, req.card_id) return {"success": err == ErrorType.SUCCESS, "company_id": engine.company_id, "action_id": req.action_id, "card_id": req.card_id, "desc": err.name} @router.get("/card-search", summary="카드 검색(전체 매핑 또는 card_id 조회)") async def card_search(card_id: Optional[str] = None, engine: TenantEngine = Depends(get_tenant_engine)): mapping = await _merged_mapping(engine) if card_id: hits = [a for a, c in mapping.items() if c == card_id] return {"company_id": engine.company_id, "card_id": card_id, "action_ids": hits, "found": bool(hits)} return {"company_id": engine.company_id, "mapping": [{"action_id": a, "card_id": c} for a, c in sorted(mapping.items())]}