Commit Graph

31 Commits

Author SHA1 Message Date
e1e519c20c [fix] negosium/backend·front: 마감된 협상이 '협상 대기'로 보이던 문제 + 종료 협상 결과 보기
- 목록 상태를 파생 계산(_effective_status): 견적 마감/마감시간 경과 + 협상생성(1) → 미참여(4).
  표시·상태필터·기본정렬 그룹에 같이 적용해 탭·KPI 카운트가 배지와 어긋나지 않게 함(DB 쓰기 없음).
  마감 일괄정리 이후 생긴 세션이 '협상 대기'에 남아 눌러도 마감 에러가 나던 헛클릭 제거.
- 미참여·협상거부 세션도 채팅 init 허용 → '결과 보기'로 지난 대화 열람. 대화 재개는 send 가
  협상중만 허용해 읽기 전용. 열 게 없는 건은 목록 has_chat(대화 이력 유무)으로 버튼 자체를 감춤.
- 종료 건은 참여 API 를 타지 않고 채팅으로 직행, 채팅 액션바는 목록 복귀만 남겨 입력 잠금.
- chain_max_round 가 단일컬럼 select 결과를 행 튜플로 읽어 매 목록 호출마다 예외 → 체인 최대차수
  0 → 옛 라운드에도 재협상 요청이 뜨고 통과되던 버그 수정(+ABC 에 중복된 죽은 구현 제거).
2026-08-10 13:57:30 +09:00
11b29b45e3 [fix] negodata·frontend·backend: 회사별 브랜드 색(primary_color) 기능 전면 제거 — 편집 UI 없이 값만 남아 적용되던 구현 정리(포털·메일·사이드바 색 솔루션 고정, 시드·응답 필드 제거) 2026-08-07 13:45:23 +09:00
71ef28110b [feat] negodata·agent·negosium: 협상 기준가 회사별 선택(공급가/매입가) + 공급사 포털 안내 회사설정화
어느 가격이 "공급사에 지불하는 단가"인지는 회사마다 달라, 컬럼을 합치는 대신 회사가 고르게 했다.
판정은 settings.features.nego_baseline_field 1순위, 미설정 회사는 price 만 숨겼으면 purchase_price 폴백.
판정식 정본은 negodata/backend/common/nego_baseline.py (agent·negosium backend 가 같은 규칙 미러).

- negodata front: 회사 설정에 협상 기준가 라디오(선택지마다 실제 나갈 문장 미리보기 + 학습 경고),
  '공급사 포털 안내' 탭 신설(협상 유의사항·헬프데스크 연락처), 용어 카탈로그에 target_price·supplier 추가.
  인터넷 최저가는 숨김 대상에서 제외(신규 견적의 유일한 목표가 후보).
  상품 등록 기본값에서 개발용 더미 제거(price 1,000,000·PROD-BAT-###·800,000·대한민국·10 EA·14).
- agent: get_item_price → get_item_baseline (기준가·호칭·회사 용어사전을 한 쿼리로),
  "기존 공급가 대비" 하드코딩을 회사 용어로 치환 + 받침 기준 조사 자동 보정,
  협상 스크립트 4종의 협력사·목표가·배송형태 용어를 {label_*} 토큰화, input_options 도 변수 치환 적용.
- negosium: 협상 화면 기준 단가·배송형태 라벨을 회사 설정 기준으로, 유의사항 본문과 헬프데스크 연락처를
  하드코딩에서 회사 설정으로(미등록 시 영역 숨김). 유의사항의 VAT·배송비 문구 삭제(IMK 0803 ⑥).
- negodata backend: LPS 검색 가격 힌트를 items.price 고정에서 기준가 규칙으로.

검증: 기준가 설정 3 × 숨김 4 = 12조합에서 협상 멘트·포털 표시·LPS 힌트가 전부 일치.
agent 테스트 176건 통과. 보고서 negodata/docs/nego-baseline-verification.md
2026-08-05 11:47:06 +09:00
9716528ce7 [feat] negosium: 협상 챗 헤더 정리 — 상품명 대표 + 견적번호
- 헤더 대표값을 협상 중인 상품명으로(여러 협상건 중 '이 건' 식별), 펄스 점·'가격 협상 채널' 문구 제거
- 견적번호(qt_number)를 백엔드 chat init → 프론트로 배선해 헤더 칩으로 노출(좁은 모바일은 숨김)
- 모바일 상품 드로어 상단에 구매사 로고+견적번호(BuyerBrandStrip) — 데스크톱 사이드바 로고의 모바일 대체
2026-07-30 08:31:16 +09:00
a56589c6d9 [feat] negosium/협상: 협상 종료폼 통일·의견 수취 — rejectRSP/CM를 단일 RejectForm(사유·희망가·의견)으로 통합해 액션바 렌더, 타결 부가정보에 의견 추가(custom.opinion), 결렬 제출값 파싱해 reject_reason/reject_price 컬럼 저장, 상품상세 필드 라벨 회사설정 연동·협상 단가 VAT별도 표기 2026-07-29 09:51:21 +09:00
d7c4e86f30 [feat] 공급사 포털: 협상완료 부가정보(select·종료 동의폼)·상태 라벨 통일·예아니오 Enter=예·목록 결과열·재협상 요청/철회 API·테스트 2026-07-24 14:18:52 +09:00
0f10b6a70f [feat] negodata·공급사포털: 상품 필드 숨김 설정·용어 카탈로그 확장·로그인 전 브랜딩·모바일 대응
- 회사 설정 hidden_fields 신설: 상품 목록·등록폼·엑셀 양식에서 감추고 목표가 후보에서도 제외
- 용어 카탈로그 9→37개(상품·협력사·견적 그룹), 목록·폼·엑셀 헤더 배선
- 엑셀 '최저한도' → '인터넷 최저가' 표기 정정(구양식 헤더는 alias 유지), 공급사 컬럼 검증 유지
- 목표가 산정내역에 적용 모드·숨김 필드 반영, 목표가 상한 라벨에 산식(상품단가×2) 표기
- 공급사 포털: 초청 링크 session_id 로 로그인 전 회사 브랜딩 조회(무인증 엔드포인트), 기본 브랜드 negotium 워드마크, negotium·AI O2O 크레딧 표기
- 목록 테이블 뷰포트 기준 전환·툴바 줄바꿈·협상현황 카드뷰로 모바일/태블릿 대응
- 이용안내 FAQ 탭 추가, 이용안내·회사설정 탭 URL 쿼리 동기화 및 빠른이동 등록
2026-07-23 11:29:35 +09:00
5d0fbbcf6a [feat] 공급사 포털·backend: 협상완료 부가정보 입력(#5)·포털 브랜딩/로고·구분삭제(#19)·카드메타 nego 저장 2026-07-22 15:20:24 +09:00
민헌
5519c6e73b feat(negotiation): 세션 목록 기본 그룹 정렬 + order 지정 시 전체 정렬
목록 진입 시 "지금 할 일"이 먼저 보이도록 기본 정렬을 개선하고,
사용자가 마감일로 직접 훑어볼 수 있는 전체 정렬 모드를 추가한다.

- 기본(order 미지정): 협상생성·협상중을 상단 그룹으로 마감 임박순,
  종료(완료·미참여·거부)는 하단 그룹으로 최근 마감순. 동일 마감은
  session_id 로 tie-break 하여 페이지네이션 안정화.
- order=asc/desc: 그룹 구분 없이 전체를 마감(qt_end_time) 기준으로 정렬.
- router: order 기본값을 "asc" → None(Optional) 로 변경해 "그룹 기본"과
  "명시적 전체 정렬"을 구분.
- frontend: SessionListParams.order 주석을 새 계약에 맞게 갱신(타입 무변경).
- tests: 기본=그룹 / 파라미터=전체 정렬 검증으로 분리(21 passed).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-08 14:12:56 +09:00
민헌
be2865a4b2 docs(common): 공통 응답 봉투 + healthz 설명 보강
- gmodel: ErrorInfo(success/code/desc) + Res_WebPacketProtocol(result/msg)
  에 description 추가 → 모든 Res_* 응답의 공통 봉투가 Swagger 에 채워짐.
- router: /healthz 에 summary/description 추가(유일하게 설명 없던 오퍼레이션).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 15:15:07 +09:00
민헌
70104404eb docs(negotiation): protocol Field + 파라미터 설명 보강
- protocol: ListItem/Res_SessionList 의 빈 Field 에 description 추가.
- session.py: page/page_size 쿼리 + session_id 경로 파라미터에 설명 추가
  (Path import). req 인자는 문법상 = ... 로 두되 requestBody required 유지.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 15:15:00 +09:00
민헌
3c56c32c85 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>
2026-07-07 15:14:53 +09:00
민헌
3b08c26908 docs(auth): protocol Field 설명 보강
Res_CreateAccount.su_id 등 빈 Field 에 description 추가 → Swagger 노출.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 15:14:46 +09:00
민헌
3b1719666f refactor(auth): popup API 리뷰 개선 + 무토큰 테스트 보강
원작성자 컨벤션 대조 리뷰 반영.

- README 엔드포인트 표에 logout·popup/status·popup/hide 추가(누락분 포함)
- user_crud: get_hide_service_info 의 불필요한 bool() 캐스트 제거
  (execute 가 단일 컬럼 select 에서 이미 스칼라 반환 — get_supplier_name 과 동일)
- account: popup 라우터를 me 뒤로 이동(로그인→계정→토큰→내정보→팝업 흐름)
- test_auth: test_popup_hide_without_token 추가(me 섹션과 무토큰 가드 대칭)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 14:36:37 +09:00
민헌
3c8923c075 feat(chat): 협상 유의사항 안내 팝업 2종 이식 + 팝업 숨김 저장 API
KT-NEGOWIZ fe_v2 의 서비스 안내 팝업을 우리 구조로 이식.

- frontend: GuideContent(공용 본문, VAT/배송비는 chat init 메타로 동적 표시)
  + ServiceInfoPopup(채팅 진입 시 자동 — 안내 보지 않기/오늘 하루 보지 않기)
  + ServiceGuidePopup(메뉴 유의사항·이용 가이드 버튼 수동 — X/배경/ESC 닫기)
  + useServiceInfoPopup 훅(서버 상태 + localStorage 오늘 하루)
  + apis/auth 에 popupStatus 쿼리·hidePopup 뮤테이션, 헬프데스크 연락처 반영,
    한국어 단어 잘림 방지(break-keep)
- backend: GET /v1/auth/popup/status, POST /v1/auth/popup/hide
  (authenticate 공통 인증 + supplier_users.hide_service_info 영구 저장), 테스트 4건
- db: supplier_users.hide_service_info 컬럼 — 00-init 테이블 정의 갱신,
  기존 DB 보정은 alters/2026-07-07-supplier-users-hide-service-info.sql 별도 파일
  (기준선 이후 보정 ALTER 는 alters/ 파일로 관리하도록 규칙 변경)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 13:41:46 +09:00
민헌
0ac37625fc Merge branch 'main' into refactor/backend
main의 negodata 기능 개발분(대시보드·회원관리/OWNER·알림함·목표가/앵커링·
견적 UX·백엔드 테스트 스위트 등 21커밋)을 backend 리팩토링 브랜치로 통합.

- 충돌: backend/router/v1/negotiation/protocol.py 1건 해결.
  refactor의 Field(description=...) 형식 유지 + main의 qt_type enum 설명
  (3=신규협상, 4=신규견적) 반영.
- 나머지(models.py, enums.py 등)는 자동 병합.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-02 09:01:48 +09:00
f19c6f57ea [chore] negodata: enum 주석 영문값 보강 + 견적상태 3종 정리 + 대시보드 정비
- enum DDL 주석에 영문값 보강(status/role/delivery/usage_type/qt_type/supplier_type)
- 견적상태 3종(생성/진행중/마감)으로 정리(ON_HOLD 제거), 배송 PARTNER→SUPPLIER
- 대시보드 손질, 관련 테스트·negosium 견적유형 주석 동반

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 17:25:38 +09:00
민헌
1a933409a3 [refactor] backend services/router 정리 — chat 분리·staticmethod 집약·protocol 문서화·테스트 보강
- router: 채팅 라우터/프로토콜을 negotiation/ 에서 chat/ 으로 분리(git mv, URL 유지).
  chat_protocol.py → chat/protocol.py (폴더당 protocol.py convention 복원), router 등록·import 갱신.
- chat_service: 순수 헬퍼/매퍼를 모듈 함수 → 클래스 @staticmethod 로 이동하고 클래스 상단에 집약.
- protocol: Req 모델 + 코드/enum 필드에 Field(description=...) 추가(Swagger 노출),
  Req 문자열 필드에 max_length(DB 컬럼 정합) 추가 → 초과 입력이 DB 오류 대신 422.
- models: updated_at 에 onupdate 추가 → UPDATE 시 자동 갱신(negodata convention 일치).
- tests: negotiation reject e2e 6케이스 + chat 순수 헬퍼 단위 4케이스 추가(45→55 passed).
- enums: 장황한 주석/docstring 축약(코드값 변경 없음).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 11:07:54 +09:00
민헌
1d4e5816b2 [fix] 재협상 가격협상 흐름 정비 — 무한루프·카드 연출·요약카드
agent 가격협상 무한 루프 수정 + 선행 chat_server 의 가격협상 연출(카드
스크립트 + 협상지표 게이지) 복원, 버짓 확인 입력가 표시 버그, 요약카드
공급사 담당자/날짜 표시 정비.

- agent: 가격협상 루프를 라운드 상한(MAX_ROUNDS)으로 종료(카드선택 실패해도
  종료 보장 — 기존엔 카드소진에만 의존해 무한 입력). chat_server iteration>=3 동작 복원.
- agent: 가격협상 턴에 선택 카드 스크립트(scripts_cards.json)를 script 로 렌더 +
  협상지표(indicator.py, 1~99/PZ) 산출해 indicator_value/bot_chat_type 전달.
  Res_Chat 에 indicator/bot_chat_type, Req_Chat 에 item_price 추가.
- agent: 가격협상_확인 멘트에 할인율(discount_rate) 표시,
  가격협상_확인_버짓이 target 이 아니라 입력가(input_price)를 표시하도록 수정.
- backend: item_price(기존 공급가) 를 agent 로 전달. 요약카드 공급사 담당자
  정보를 supplier_users(빈 이메일) 대신 partner.suppliers.manager_* 에서 조회,
  ChatSummary.supplier_manager_phone 추가.
- frontend: 요약카드 협상 개시/종료 시각을 "YYYY년 MM월 dd일 HH시 MM분 SS초"(KST)
  로, 공급 계약 만료일(+1년) ISO 파싱, 우선협상 대상자에 공급사 연락처/이메일 표시.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-24 11:52:34 +09:00
민헌
8f070e362b feat(chat): agent 연동 정리 — mock 제거·DB 데이터 연동·표현 passthrough
- MockAgentClient/use_mock 분기와 mock 전용 turn/count_bot_messages 제거 (항상 HttpAgentClient 위임)
- agent RL state 입력을 실 DB 로 연동: anchor_price=quotation_settings.anchoring_value 기반 계산, partner_count=견적당 세션 수 (quotation_settings 모델 추가)
- 재견적 배송형태(delivery_type) 캡처: 배송형태선택 단계 선택값을 summaryCM 요약에 반영 (DeliveryType enum 추가)
- 표현 계약 passthrough: agent 응답의 bot_chat_type/indicator_value 를 우선 사용하고 없으면 step+qt_type 으로 폴백, indicator_value 컬럼 영속/전달
- 턴당 중복 조회 제거: item/last_price 를 1회 로드해 재사용
- 관련 테스트 추가(배송형태 캡처, passthrough)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 17:32:50 +09:00
c3d96fb7d3 모든 프로젝트 1차 병합 . 2026-06-19 08:40:09 +09:00
a52321e68d Merge branch 'main' of https://gitea.o2o.kr/Negosium/o2o-negosium 2026-06-18 16:33:16 +09:00
b0b787a8ce cors 문제 해결 . 2026-06-18 16:30:03 +09:00
민헌
dcce82a630 feat(backend): 협상 채팅(chat) API + agent 위임
- /v1/negotiation/sessions/{id}/chat/{init,messages,send} 추가
- agent(9500) 위임 어댑터(IAgentClient) + mock(use_mock) 격리 → agent 미연동 시 1402 graceful degrade
- negotiation.chats 메시지 영속화(meta JSONB) + 종료 시 세션 입찰/거부 확정(단일 트랜잭션)
- 동시전송 가드(유저 메시지 pre-claim/CHAT_IN_PROGRESS) + 실패 시 롤백, 마감/만료 분기, init 만료 정리
- ChatSender enum, chat 에러코드(1400~1403), chats ORM 모델, AgentConfig
- 테스트 10건(test_chat.py), AGENT_INTEGRATION.md 연동 규약 문서

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 14:24:57 +09:00
민헌
d199c1dec1 feat(backend): 협상 거부(reject) 기능
- POST /v1/negotiation/sessions/{session_id}/reject (Req_Reject/Res_Reject)
- 참여와 공통 검증(인증/소유/세션상태/견적마감/마감시간)을
  _load_actionable_session 헬퍼로 추출해 participate·reject 재사용
- 거부 불가 상태: 협상완료/미참여/협상거부 → NEGO_NOT_PARTICIPABLE
- 성공 시 세션을 협상거부(5)로 전이하고 reject_reason 저장(최대 255자)
- 빈 사유는 INVALID_REQUEST_DATA

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 13:20:29 +09:00
민헌
2480a47efe feat(backend): 협상 세션 목록 + 참여 기능
- GET /v1/negotiation/sessions: 로그인 공급사의 세션 목록(필터/정렬/페이지네이션)
  · qt_end_time 은 견적(quotation.end_time) 기준, sessions⨝items⨝quotations 조인
  · status/qt_type 은 정수 코드로 응답(라벨 매핑은 프론트)
- POST /v1/negotiation/sessions/{session_id}/participate: 협상 참여
  · 검증: 소유(공급사 대조)→세션상태→견적마감→마감시간, 에러코드 1300~1304
  · 협상생성→협상중, 견적→견적진행중 (협상중/완료는 무변경 진입)
  · 마감초과 시 협상생성 세션만 미참여로 정리
- DBType.NEGOTIATION/QUOTATION, items/sessions/quotations 모델
- QtType/SessionStatus/QuotationStatus enum, AuthService.authenticate 공통화
- 협상 e2e 테스트(test_negotiation.py)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 12:32:32 +09:00
민헌
698d4e72d4 feat(backend): 로그아웃 + stateful 토큰 검증 (단일 세션 즉시 폐기)
- POST /v1/auth/logout: 저장된 access/refresh 토큰 행 삭제 → 즉시 로그아웃
- /me, refresh 에서 제시된 토큰을 저장된 토큰과 대조(불일치 시 TOKEN_REVOKED=1203)
  → 로그아웃/타기기 재로그인으로 교체된 토큰을 만료 전이라도 차단
- crud get_token 추가, ErrorType.TOKEN_REVOKED(1203) 추가, Res_Logout 프로토콜
- 로그아웃/단일세션 무효화 e2e 테스트 추가 (test_auth.py)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 11:26:08 +09:00
민헌
2832162672 feat(backend): CORS 허용 오리진 설정 추가
- WebServerConfig.cors_origins(list) 추가, config 의 오리진이 있을 때만 CORSMiddleware 적용
- 명시적 오리진이라 allow_credentials=true (Authorization 헤더 허용)
- 로컬 기본값: http://localhost:5173, http://127.0.0.1:5173 (Vite)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 11:16:43 +09:00
민헌
5940f54d2b feat(backend): supplier_users 기반 인증 재구축 및 단일세션 토큰 저장
- tbl_account 예시 인증 제거, supplier_users 기반으로 일원화(generic 네이밍 재사용)
- DBType USER/PARTNER 분리, AccountStatus/UserRole/TokenType enum 추가
- 보호 요청 시 su_id DB 존재/활성 검증(stateless JWT 빈틈 보완), 공급사명(partner.suppliers) 응답 포함
- 로그인 시 단일 세션 access/refresh 토큰을 supplier_user_tokens 에 저장(재로그인 시 교체)
- greenlet 의존성 추가, 인증 e2e 테스트(test_auth.py) 재작성

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 11:16:33 +09:00
212725e5f9 [chore] 추적된 .pyc 제거 + 루트 .gitignore 추가
backend/__pycache__ 등에 추적되던 .pyc 51개를 인덱스에서 제거하고,
루트 .gitignore(__pycache__/, *.py[cod], .venv/, openapi.json, CLAUDE.md)를 추가한다.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 08:39:39 +09:00
f7833ba466 백엔드 프레임 설계 2026-06-15 15:53:39 +09:00