docs(chat): protocol Field + 경로 파라미터 설명 보강

- protocol: ChatSummary 전 필드 + ChatMessage/Res_ChatInit/Res_ChatSend 의
  빈 Field 에 description 추가. 혼동되던 두 배송 필드를 조립 코드 기준으로
  구분 명시(item_delivery_type=상품 기본 폴백 / delivery_type=배송형태선택 결과).
- chat.py: session_id 경로 파라미터에 Path(description=...) 추가.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
민헌 2026-07-07 15:14:53 +09:00
parent 3b08c26908
commit 3c56c32c85
2 changed files with 50 additions and 50 deletions

View File

@ -1,4 +1,4 @@
from fastapi import APIRouter, Depends
from fastapi import APIRouter, Depends, Path
from fastapi.security import HTTPAuthorizationCredentials
from common.models.gmodel import UserInfo
@ -17,7 +17,7 @@ router = APIRouter(prefix="/v1/negotiation", tags=["Chat"], responses={404: {"de
description="채팅 화면 진입용. 상품/견적 정보 + 현재 세션 상태 + 마감 시각(타이머)을 반환한다. 소유(공급사) 검증.",
)
async def chat_init(
session_id: str,
session_id: str = Path(description="대상 협상 세션 uuid"),
user_info: UserInfo = Depends(IsValidAccessToken),
credentials: HTTPAuthorizationCredentials = Depends(security),
service: ChatService = Depends(),
@ -32,7 +32,7 @@ async def chat_init(
description="세션의 대화 말풍선 목록(seq 오름차순). 비어 있고 협상중이면 오프닝 메시지를 생성해 포함한다.",
)
async def chat_messages(
session_id: str,
session_id: str = Path(description="대상 협상 세션 uuid"),
user_info: UserInfo = Depends(IsValidAccessToken),
credentials: HTTPAuthorizationCredentials = Depends(security),
service: ChatService = Depends(),
@ -47,8 +47,8 @@ async def chat_messages(
description="유저 입력을 보내고 agent 가 만든 봇 응답 1건을 반환한다(append-only). 종료 시 세션 입찰을 확정한다.",
)
async def chat_send(
session_id: str,
req: Req_ChatSend,
session_id: str = Path(description="대상 협상 세션 uuid"),
req: Req_ChatSend = ...,
user_info: UserInfo = Depends(IsValidAccessToken),
credentials: HTTPAuthorizationCredentials = Depends(security),
service: ChatService = Depends(),

View File

@ -17,42 +17,42 @@ from common.models.gmodel import Res_WebPacketProtocol, WebPacketProtocol
# 협상 결과 요약 카드(summaryRSP/summaryCM)에 표시할 데이터. 종료 스텝에서만 채워 내려간다.
# 필드명은 프론트 ChatSummary 타입과 1:1 (item_isVAT 등 camelCase 유지).
class ChatSummary(WebPacketProtocol):
md_name: str = ""
md_email: str = ""
md_phone_number: str = ""
item_code: str = ""
item_name: str = ""
item_spec: str = ""
item_moq: str = ""
item_model: str = ""
item_maker: str = ""
item_isVAT: bool = False
item_lead_time: str = ""
item_display_date: str = ""
item_delivery_type: str = ""
final_price: int = 0
nego_start_date: str = ""
nego_end_date: str = ""
supplier_name: str = ""
supplier_manager_name: str = ""
supplier_manager_email: str = ""
supplier_manager_phone: str = ""
delivery_type: Optional[str] = None
md_name: str = Field("", description="견적 담당 MD(고객사 담당자) 이름")
md_email: str = Field("", description="MD 이메일")
md_phone_number: str = Field("", description="MD 연락처")
item_code: str = Field("", description="상품 코드")
item_name: str = Field("", description="상품명")
item_spec: str = Field("", description="상품 규격")
item_moq: str = Field("", description="최소 주문 수량")
item_model: str = Field("", description="모델명")
item_maker: str = Field("", description="제조사")
item_isVAT: bool = Field(False, description="VAT 포함 여부")
item_lead_time: str = Field("", description="배송 리드타임(일)")
item_display_date: str = Field("", description="상품 게시일(견적 시작 시각, ISO 8601)")
item_delivery_type: str = Field("", description="상품 기본 배송유형 라벨(선택값 없을 때 폴백용)")
final_price: int = Field(0, description="최종 제시가(원)")
nego_start_date: str = Field("", description="협상 시작 시각(견적 시작, ISO 8601)")
nego_end_date: str = Field("", description="협상 종료 시각(견적 마감, ISO 8601)")
supplier_name: str = Field("", description="공급사명")
supplier_manager_name: str = Field("", description="공급사 담당자 이름")
supplier_manager_email: str = Field("", description="공급사 담당자 이메일")
supplier_manager_phone: str = Field("", description="공급사 담당자 연락처")
delivery_type: Optional[str] = Field(None, description="재견적 '배송형태선택'에서 공급사가 고른 배송형태 라벨(재협상은 단계 없어 null)")
# 말풍선 한 건. sender 는 ChatSender 정수 코드(1=BOT, 2=USER)로 내려가고 라벨 매핑은 프론트가 한다.
class ChatMessage(WebPacketProtocol):
chat_id: str = ""
session_id: str = ""
seq: int = 0
chat_id: str = Field("", description="채팅 메시지 식별자(uuid)")
session_id: str = Field("", description="소속 협상 세션 uuid")
seq: int = Field(0, description="세션 내 메시지 순번")
sender: int = Field(0, description="발신자 코드 (ChatSender: 1=BOT, 2=USER)")
script: str = ""
script: str = Field("", description="말풍선 본문 텍스트")
user_input_type: Optional[str] = Field(None, description="유저 입력 종류: text|percent|price")
step: str = ""
step: str = Field("", description="agent 내부 단계 코드")
display_step: str = Field("", description="agent client_step (표시용 단계)")
next_input_mode: Optional[str] = Field(None, description="다음 입력 모드: confirm|yes_no|percent|price|delivery_type")
next_input_type: Optional[list[str]] = Field(None, description="다음 입력 선택지(버튼 라벨)")
chat_end: bool = False
chat_end: bool = Field(False, description="이 메시지로 협상이 종료되는지 여부")
indicator_value: Optional[float] = Field(None, description="협상 지표(1~99). 가격협상 턴에 표시")
bot_chat_type: Optional[str] = Field(None, description="폼 종류: summaryRSP|summaryCM|rejectRSP|rejectCM|indicator")
summary: Optional[ChatSummary] = Field(None, description="summaryRSP/summaryCM 일 때만 채워짐")
@ -60,28 +60,28 @@ class ChatMessage(WebPacketProtocol):
# 채팅 진입 — 상품/견적 메타 + 현재 세션 상태 + 마감 시각(타이머용)
class Res_ChatInit(Res_WebPacketProtocol):
session_id: str = ""
session_id: str = Field("", description="협상 세션 uuid")
session_status: int = Field(0, description="세션 상태 코드 (SessionStatus: 1=생성 2=진행중 3=완료 4=미참여 5=거부)")
quotation_id: str = ""
quotation_id: str = Field("", description="소속 견적 uuid")
quotation_end_time: str = Field("", description="견적 마감 시각 (ISO 8601, 타이머용)")
quotation_memo: str = ""
item_id: str = ""
item_name: str = ""
item_code: str = ""
item_image: str = ""
item_price: int = 0
item_model_name: str = ""
item_maker_name: str = ""
item_spec: str = ""
item_lead_time: str = ""
item_min_order_quantity: str = ""
item_vat_yn: Optional[bool] = None
item_delivery_fee_yn: Optional[bool] = None
quotation_memo: str = Field("", description="견적 메모")
item_id: str = Field("", description="상품 uuid")
item_name: str = Field("", description="상품명")
item_code: str = Field("", description="상품 코드")
item_image: str = Field("", description="상품 이미지 URL")
item_price: int = Field(0, description="상품 가격(원)")
item_model_name: str = Field("", description="모델명")
item_maker_name: str = Field("", description="제조사")
item_spec: str = Field("", description="상품 규격")
item_lead_time: str = Field("", description="배송 리드타임(일)")
item_min_order_quantity: str = Field("", description="최소 주문 수량")
item_vat_yn: Optional[bool] = Field(None, description="VAT 포함 여부(미설정 시 null)")
item_delivery_fee_yn: Optional[bool] = Field(None, description="배송비 포함 여부(미설정 시 null)")
# 대화 히스토리(재진입 복원)
class Res_ChatMessages(Res_WebPacketProtocol):
items: list[ChatMessage] = []
items: list[ChatMessage] = Field(default_factory=list, description="대화 말풍선 목록 (seq 오름차순)")
# 한 턴 전송. user_input 은 버튼 텍스트 또는 가격/퍼센트 문자열.
@ -92,5 +92,5 @@ class Req_ChatSend(WebPacketProtocol):
# append-only: 새 봇 메시지 1건 + 갱신된 세션 상태만 반환(전체 refetch 회피)
class Res_ChatSend(Res_WebPacketProtocol):
message: Optional[ChatMessage] = None
session_status: int = 0
message: Optional[ChatMessage] = Field(None, description="새로 생성된 봇 메시지 1건(append-only)")
session_status: int = Field(0, description="갱신된 세션 상태 코드 (SessionStatus)")