o2o-negosium-original/backend
hbyang ed175c5b65 [feat] agent: Req_Chat 슬림화 — 협상 컨텍스트를 DB 조회로 전환 + CRUD 계층 도입
- Req_Chat 을 session_id/user_input/client_step 3필드로 축소 — rq_type·목표가·앵커·품목가·
  매출액·유통코드·파트너 유형·수용률 필드 전부 제거
- NegotiationContextLoader 신설: 세션 시작 시 공유 DB 1회 조회로 컨텍스트 확정
  · rq_type = sessions.qt_type ({1,3}→재협상 / {2,4}→재견적)
  · anchor = sessions.anchoring_price(박제) — NULL 이면 무할인 폴백 anchor=target (v1.2 정책 승계)
  · 매출액 = suppliers.total_revenue(KTC 미러), 유통코드 = quotations.supplier_type 매핑
  · 파트너 유형 = 상품별 distinct supplier 수 → PartnerType enum(0=NONE/1=SINGLE/2=MULTIPLE)
- 가격 수용률은 세션 내 동적 계산: max(0, (첫 제시가−현재가)/첫 제시가)
- DB 쿼리를 backend crud 패턴으로 분리: INegoContextCRUD(ABC)+NegoContextCRUD,
  IChatSessionRepository 인터페이스 추가 (테스트 더블 주입 가능)
- 와일드카드 1% 수락 시 합의가=offer_1pct 반영 + Res_Chat.settled_price 신설 —
  backend 요약/입찰가가 이를 최우선 사용 (19,800원 수락이 20,000원으로 기록되던 버그 수정)
- backend: agent 전송 바디 3필드로 축소, 앵커/파트너 조회 메서드 제거,
  test_anchoring_chat 을 새 구조로 재작업(박제 소비/폴백 검증은 agent 테스트로 이관)
- 데모 페이지(/demo·negotiation_demo.html) 제거 — 컨텍스트 주입 경로 폐지로 무의미
- 테스트: agent 83/83, backend 57/57 (컨텍스트 로더 실데이터 왕복 4종 + CRUD 더블 검증 포함)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-07 09:44:21 +09:00
..
common refactor(anchoring): 도메인 이름 전면 개편 — adjustments·anchoring_value/price·price_range·sample 용어 통일 2026-07-06 11:17:01 +09:00
config Merge branch 'feature/negodata' 2026-06-23 08:31:13 +09:00
crud refactor(anchoring): 도메인 이름 전면 개편 — adjustments·anchoring_value/price·price_range·sample 용어 통일 2026-07-06 11:17:01 +09:00
loadtest chore(backend): 로컬 실행/부하테스트 스크립트 추가 2026-06-18 11:17:37 +09:00
router Merge branch 'main' into refactor/backend 2026-07-02 09:01:48 +09:00
scripts [chore] negodata: enum 주석 영문값 보강 + 견적상태 3종 정리 + 대시보드 정비 2026-06-30 17:25:38 +09:00
services [feat] agent: Req_Chat 슬림화 — 협상 컨텍스트를 DB 조회로 전환 + CRUD 계층 도입 2026-07-07 09:44:21 +09:00
tests [feat] agent: Req_Chat 슬림화 — 협상 컨텍스트를 DB 조회로 전환 + CRUD 계층 도입 2026-07-07 09:44:21 +09:00
.dockerignore chore(config): agent mock 모드 제거 및 .dockerignore 정리 2026-06-19 17:32:38 +09:00
conftest.py feat(backend): supplier_users 기반 인증 재구축 및 단일세션 토큰 저장 2026-06-18 11:16:33 +09:00
Dockerfile Agent 서버 구축: 멀티테넌트 협상 PoC (UCB Q-Table 학습 + /chat + 14 API + 학습검증 하네스), config 단일화(local.toml) + 빌드 경량화 2026-06-17 11:10:03 +09:00
pytest.ini 백엔드 프레임 설계 2026-06-15 15:53:39 +09:00
README.md requirement.dev.txt 삭제 . 2026-06-15 15:57:20 +09:00
requirements.txt feat(backend): 협상 채팅(chat) API + agent 위임 2026-06-18 14:24:57 +09:00
run_local_locust.sh chore(backend): 로컬 실행/부하테스트 스크립트 추가 2026-06-18 11:17:37 +09:00
run_local_pgwatch.sh chore(backend): 로컬 실행/부하테스트 스크립트 추가 2026-06-18 11:17:37 +09:00
run_local_server.sh chore(backend): 로컬 실행/부하테스트 스크립트 추가 2026-06-18 11:17:37 +09:00
web_main.py 백엔드 프레임 설계 2026-06-15 15:53:39 +09:00

Negosium Backend

DerbyMasters_Server 아키텍처를 이식한 FastAPI 골격. 기능은 JWT id/pw 로그인만 예시 구현. 실행·테스트·벤치마크 종합은 레포 최상위 README 참고.

디렉토리 구조

backend/
├── web_main.py                  # 엔트리포인트 (uvicorn)
├── config/                      # 환경설정 (APP_ENV 별 toml 로드)
├── common/
│   ├── enums.py                 # ErrorType / DBType / DBWRType / EXCEPTION_*
│   ├── models/gmodel.py         # 프로토콜 베이스 (WebPacketProtocol 등)
│   └── database/
│       ├── db_session_manager.py# ★ DB Read/Write + 람다 실행 핵심
│       └── model/models.py      # ORM 모델 (tbl_account)
├── crud/user_crud.py            # DB 접근 (I*CRUD 인터페이스 + 구현)
├── services/auth_service.py     # 비즈니스 로직
└── router/
    ├── router.py                # FastAPI app
    └── v1/
        ├── auth/{account,protocol}.py   # 엔드포인트 / Req_·Res_
        └── validator/dependencies.py    # ★ JWT 발급·검증, 해시, RemoveNoneResponse

핵심 패턴

  • MVC: router(컨트롤러) → service(로직) → crud(쿼리). crud 는 인터페이스/구현 분리.
  • Depends 주입: service 가 IUserCRUD = Depends(UserCRUD), router 가 Depends(AuthService), 인증은 Depends(IsValidAccessToken).
  • DB Read/Write 분리: DBType × DBWRType 조합마다 별도 async 엔진(조회=Read, 변경=Write).
  • 람다 DB 실행: service 는 세션을 직접 열지 않고 람다를 매니저에 넘긴다. 세션/트랜잭션은 매니저가 책임.
    err, acc = await DB_SESSION_MNG.execute_lambda(           # 단일 조회
        tbl_account.DBType(), DBWRType.DB_READ.value, lambda s: crud.get_account_by_id(s, id))
    err = await DB_SESSION_MNG.execute_lambda_run(            # 여러 변경 = 1 트랜잭션
        [tbl_account.DBType()], [lambda s: crud.update_last_login(s, uid)])
    
  • 비동기: 전 계층 async/await, SQLAlchemy async + asyncpg, task 단위 scoped session.
  • Protocol 규약: 모든 패킷 WebPacketProtocol 상속, Req_*/Res_*(응답엔 result: ErrorInfo), 라우터별 protocol.py.
  • ResponseNone: 응답의 None 필드 재귀 제거(RemoveNoneResponse).
  • bcrypt 비차단: GetHashedPW/VerifyPW 를 asyncio.to_thread 로 오프로드(이벤트 루프 비차단). → 벤치마크

엔드포인트

Method Path 설명
POST /v1/auth/create 계정 생성 (pw bcrypt 해시)
POST /v1/auth/login 로그인, access/refresh 토큰 발급
POST /v1/auth/refresh_token access 토큰 재발급 (refresh 필요)
GET /v1/auth/me 내 정보 (access 토큰 필요)

실행 / 테스트

# 레포 최상위에서 docker compose up -d (backend만; DB 는 외부 PostgreSQL). 상세는 루트 README.
cd backend
pip install -r requirements.txt        # 실행
python web_main.py                      # APP_ENV 기본 local
pip install pytest pytest-asyncio httpx  # 테스트 도구
python -m pytest
  • 서버: http://localhost:9300/docs
  • 환경: config.{local,test,docker}.toml (APP_ENV 로 선택, docker 는 DB 호스트=host.docker.internal)