Merge remote-tracking branch 'origin/main' into feature/backend-frontend
This commit is contained in:
commit
e7be7d5b5f
@ -13,6 +13,7 @@ Chat_server 구조 참고, 동적 import 해킹/특정사 표현은 제거(CLEAN
|
||||
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
from typing import Any, Dict, Optional
|
||||
|
||||
from common.database.db_session_manager import DB_SESSION_MNG
|
||||
@ -24,6 +25,8 @@ from tenancy.config import TenantConfig
|
||||
|
||||
_RQ_FILES = {"재협상": "scripts_renegotiation.json", "재견적": "scripts_requote.json"}
|
||||
_CARD_SOURCE_DB = "backoffice_db"
|
||||
# `{name}` 단일 토큰만 매칭(색 마커 `{{강조|...}}` 는 내부 `|` 로 인해 비매칭 → 보존).
|
||||
_VAR_TOKEN_RE = re.compile(r"\{(\w+)\}")
|
||||
|
||||
|
||||
class ScriptRepository:
|
||||
@ -125,21 +128,23 @@ class ScriptRepository:
|
||||
}
|
||||
|
||||
def format_script(self, text: str, variables: Optional[Dict[str, Any]] = None) -> str:
|
||||
"""{company_name}/{service_name} + 협상 변수 치환. 누락 변수는 원형 유지(KeyError 방지)."""
|
||||
"""{company_name}/{service_name} + 협상 변수 치환. 누락 변수는 원형 유지.
|
||||
|
||||
정규식으로 `{name}` 단일 토큰만 치환한다 — str.format_map 은 `{{`·`}}` 를 이스케이프로
|
||||
해석해 색 마커 `{{강조|...}}` 를 `{강조|...}` 로 붕괴시키므로 쓰지 않는다.
|
||||
색 마커는 내부에 `|`(비-\\w)가 있어 `\\{(\\w+)\\}` 에 매칭되지 않아 그대로 보존된다.
|
||||
"""
|
||||
if not text:
|
||||
return text
|
||||
ctx = self._brand_vars()
|
||||
if variables:
|
||||
ctx.update({k: v for k, v in variables.items() if v is not None})
|
||||
|
||||
class _Safe(dict):
|
||||
def __missing__(self, key):
|
||||
return "{" + key + "}"
|
||||
def _repl(m):
|
||||
key = m.group(1)
|
||||
return str(ctx[key]) if key in ctx else m.group(0) # 미등록 토큰은 원형
|
||||
|
||||
try:
|
||||
return text.format_map(_Safe(ctx))
|
||||
except (ValueError, IndexError):
|
||||
return text # 형식 토큰 충돌 시 원형
|
||||
return _VAR_TOKEN_RE.sub(_repl, text)
|
||||
|
||||
def get_step(self, step: str, rq_type: str = "재협상", variables: Optional[Dict[str, Any]] = None) -> Optional[dict]:
|
||||
"""step 정의를 반환하되 script 를 치환해서 돌려준다."""
|
||||
|
||||
@ -89,6 +89,14 @@ def test_client_step_and_variable_mapping_load():
|
||||
assert vm["인터넷 최저가"] == "internet_min_price"
|
||||
|
||||
|
||||
def test_format_script_preserves_color_markers():
|
||||
"""변수 치환이 색 마커 {{강조|...}} 를 보존해야 한다(회귀: format_map 이 {{}} 를 {} 로 붕괴시킴)."""
|
||||
repo = _repo()
|
||||
out = repo.format_script("**{input_price}원**·{{안내|{target}원}}·{unknown}",
|
||||
{"input_price": 9800, "target": 10000})
|
||||
assert out == "**9800원**·{{안내|10000원}}·{unknown}" # 마커 보존 + 변수 치환 + 미등록 원형
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_resolve_card_script_file_mode_default():
|
||||
"""기본(source_type='file'): resolve_card_script 가 파일 카드 멘트를 반환(하위호환)."""
|
||||
|
||||
@ -658,12 +658,3 @@ ORDER BY company_id, supplier_type, price_range_index, adjustment_id DESC;
|
||||
-- 기준선(2026-07-07 main 스키마)까지의 보정은 이 섹션에 있고, 그보다 오래된 DB 는 git 이력의 04-alter*.sql 을 먼저 적용.
|
||||
-- 기준선 이후의 새 스키마 변경은 위 테이블 정의를 갱신하고, 보정 ALTER 는 alters/ 아래 별도 파일로 만들어 적용한다.
|
||||
|
||||
-- [2026-07-07] 협상 카드: script 길이 제한 해제(TEXT) + 톤·전략 분류 컬럼
|
||||
ALTER TABLE card.nego_cards ALTER COLUMN script TYPE TEXT;
|
||||
ALTER TABLE card.wild_cards ALTER COLUMN script TYPE TEXT;
|
||||
ALTER TABLE card.nego_cards
|
||||
ADD COLUMN IF NOT EXISTS tone SMALLINT NULL, -- 카드 톤(CardTone): 1=강경, 2=정중, 3=우호, 4=중립, 5=단호
|
||||
ADD COLUMN IF NOT EXISTS strategy_type SMALLINT NULL; -- 전략 유형(CardStrategyType): 1=경쟁, 2=수용, 3=고수, 4=협력, 5=선점, 6=종결
|
||||
ALTER TABLE card.wild_cards
|
||||
ADD COLUMN IF NOT EXISTS tone SMALLINT NULL, -- 카드 톤(CardTone): 1=강경, 2=정중, 3=우호, 4=중립, 5=단호
|
||||
ADD COLUMN IF NOT EXISTS strategy_type SMALLINT NULL; -- 전략 유형(CardStrategyType): 1=경쟁, 2=수용, 3=고수, 4=협력, 5=선점, 6=종결
|
||||
Loading…
Reference in New Issue
Block a user