o2o-negosium-original/docs/negotiation-qa-checklist.md

9.6 KiB
Raw Permalink Blame History

협상 QA 체크리스트 (260727 요청 검증)

대상: negodata 어드민(:3000) + negosium 공급사 포털(:3300). 두 앱을 함께 돌려야 하는 플로우라 루트 docs/에 둔다. 형식: 케이스별 ~하면 → ~나와야 한다. 근거는 코드 검증(2026-07-30) 기준. ⚠=현재 알려진 이슈. 런타임 주의: negosium front/backend는 이미지 빌드라 코드 수정은 재빌드해야 반영된다.


0. 요청사항 반영 현황 (코드 검증 결과, Excel 상태열 아님)

# 요청 판정 비고
2 견적관리 리스트+히스토리·상세 ✅ /quotation + ?detail= 시트(협상현황/대화/카드, 라운드 타임라인)
3 재협상 리스트·심사 ✅ /renegotiation 대기/승인/반려
4 MD→구매담당자·판매가 미노출·위치 ✅
5/23 목표가=매입가×(1−네고율) 자동 ✅ 재/재견적 한정, 네고율=견적세팅 목표마진
6 공급가=매입가 일원화 ⚙ 설정 코드 지원됨(hideCls). IMK hidden_fields에 "price" 추가하면 매입가만 남음
7 최저가 크롤 + VAT산식 ⚠ 인프라 / 논이슈 VAT는 설정·아이템별 처리(논이슈). 단 dev의 lps-worker 크래시+수집테이블 0행 → 수집 파이프라인 확인 필요
8 신규 상품 공급사 입력칸 ✅
9 SG명/유통레벨 콤보·취급상품 삭제 ❌ 미구현 §9 참조
10 리드타임→표준납기 ✅ 수정 Summary.tsx 하드코딩 라벨 회사설정 반영으로 수정(2026-07-30)
11 단가 VAT별도 ✅ 회사설정 item_vat_yn 동적(IMK는 vat_yn hidden)
12 앵커 10원 반올림 ✅ calc_anchoring_price + 카드 카운터(compute_counter) + 와일드카드 1%(2026-07-31 수정) 모두 10원 반올림
13 절충안 계산식 ✅ compute_counter 점검, 버그 없음
14/17 결렬 희망가 입력란 통일 ✅ 단일 RejectForm
15 마무리 배송 콤보/기타의견/투찰요약 ✅ ExtraInfoBar가 session_fields select 렌더 → 콤보 [직납/IMK배송/IMK집배송]
16 제안가 갭·반올림 ✅ 갭은 정상(목표가=후보 min×수수료). 봇 제안가(카운터·와일드카드 1%)도 10원 반올림 반영(2026-07-31)
18/22 성공률 기준·결렬 무관 ✅ 게이지는 참고용, 판정과 무관(§D). 타결=목표가 아래로/봇 카운터 수락, 결렬=카드3+최종제안 소진까지 목표가 위
19/25 종료 의견 단계 ✅ 타결 ExtraInfoBar(custom.opinion)+결렬 RejectForm 의견
20 결렬사유 상시노출·필수 ✅ 검증 결렬 세션 9/9 사유 존재. §20 참조
21 카드 3회 초과 ✅ 정상 3회=협상카드 한도. 와일드카드·최종제안은 별도로 붙는 구조라 보이는 카드가 3장을 넘을 수 있음(§21)
24 목표가 필드 1→3.낙찰기준 이동 ✅

A. 견적 생성 (어드민)

  • A1 재/재견적에서 매입가 10,000·네고율(견적세팅 목표마진) 2% 입력 → 목표가(구매담당자 제시가) 필드에 9,800 자동 채움(10원 반올림)
  • A2 목표가 직접 안 건드리고 생성 → md_price=null로 전송, 서버가 후보 최솟값으로 재산정
  • A3 신규협상/신규견적 → 매입가 후보 빠지고 인터넷최저가만 사용 → 자동 목표가가 매입가 기반이 아님(A1과 다른 게 정상)
  • A4 1.기본정보엔 목표가 없어야 / 3.낙찰기준 스텝에 목표가+산정후보 나와야
  • A5 판매가 입력칸 없어야 / 라벨 "구매담당자 제시가"

B. 앵커·제안가

  • B1 협상 시작 → 세션 앵커가 = 목표가×(1−1%), 끝자리 0 (예 목표 7,650 → 앵커 7,570)
  • B2 봇 재제안가 전부 끝자리 0 — 카드 카운터(절충가·목표가 제시)와 와일드카드 1% 인하가 포함 (예 제시 15,555 → 1% 인하가 15,400). 1원 단위가 보이면 불량

C. 협상 진행 (실시간 챗, 공급사 포털)

  • C1 제시가 ≤ 앵커가 → 즉시 협상완료(투찰 확정), 성공률 99
  • C2 앵커가 < 제시가 ≤ 앵커×1.02 → 와일드카드 1% 인하 요청(세션 1회), 성공률 99~80
  • C3 앵커×1.02 초과 → 일반 협상카드로 재제안(최대 3번), 성공률 표시(제시가 낮을수록↑)
  • C4 카드 소진 또는 재제안 3번 후에도 앵커 밑 못 내림 → 협상 실패(결렬, 투찰 없음)
  • C5 카드 사용한도 3은 협상카드에만 적용. 와일드카드·최종제안은 별도로 붙어 공급사가 보는 카드가 3장을 넘을 수 있음(정상, §21)
  • C6 단가는 VAT별도 표기(IMK는 VAT 라벨 자체 숨김)

D. 타결/결렬 판정 & 성공률 게이지

  • 판정 규칙: 유저가 목표가 아래로 내리거나 봇이 되받은 제시가(카운터)를 수락하면 타결. 카드(3장)+최종제안까지 다 소진될 때까지 목표가 위에서 버티면 결렬.
  • D1 성공률 게이지는 참고용일 뿐 판정과 무관 — 제시가 낮을수록 게이지↑(상한 99, 100% 도달 안 함).
  • D2 성공률 낮아도 무조건 결렬 아님. 최종 마감(낙찰/개찰)은 별도 기준(§G).

E. 협상 타결(완료) 마무리

  • E1 협상완료 → 부가정보 입력 단계 등장 (표준납기·최소주문수량·발주배수·배송유형·의견)
  • E2 배송유형 → **콤보 [직납/IMK배송/IMK집배송]**로 떠야 (자유입력·다른 라벨이면 불량)
  • E3 의견(선택) 작성 → custom.opinion 저장돼야
  • E4 입력 완료 → 투찰결과 요약 갱신 후 최종 안내, 요약에 부가정보·의견 반영
  • E5 어드민 상세(협상현황/요약)에서 부가정보 표시+잠금(읽기전용)

F. 협상 결렬(실패)

  • F1 결렬 → 결렬 사유 입력 단계 항상 노출 + 필수(견적/유형 무관 동일 폼)
  • F2 사유 프리셋(단가인상/수량/단종/품절)+기타, 기타 선택 시 사유 텍스트 필수
  • F3 희망가격 입력 = 단일 폼(RSP/CM 동일)
  • F4 의견(선택) 작성 가능
  • F5 검증: 결렬(협상거부) 세션은 100% 사유가 기록돼야 (사유 없는 결렬 세션 = 불량). §20

G. 마감 · 낙찰/개찰

  • G1 투찰가 ≤ 앵커가 → 낙찰
  • G2 앵커~목표가 → 1:1은 사용자 지정(mid_action), 1:N은 낙찰
  • G3 목표가 초과 → 1:1 사용자 지정(over_action, 관례 개찰), 1:N 낙찰
  • G4 동가(최저 2곳+)·전원 미응찰·협상거부 → 개찰(낙찰자 미정, 결렬 아님) / 마감사유 라벨 정확히

H. 재협상 요청·심사 (공급사→어드민)

  • H1 개찰 마감 + 본인 마지막 라운드 → 재협상 요청 가능(사유+희망가), 담당자 알림 1건
  • H2 낙찰건/남의 세션 요청 → 거부
  • H3 같은 세션 2회 요청 → 2번째 거부; 철회 후 재요청 가능
  • H4 어드민 /renegotiation 대기 탭 접수 → 승인 시 다음 차수 견적 생성, 반려 시 사유 필수

알려진 이슈 상세

§9. 협력사 SG명/유통레벨 콤보·취급상품 삭제 — 미구현

요청 4가지 모두 현재 구조와 다르다:

  1. 분류카테고리 → SG명: 지금 '분류카테고리'는 입력 필드가 아니라 취급상품에서 파생 집계되는 읽기전용 값(SupplierItemsManager.tsx). 회사 라벨(labels.category)로 "SG명" 표기만 되지, 직접 고르는 필드가 아님.
  2. 선택콤보(취급 SG명): 등록된 SG명 중 선택하는 콤보 없음.
  3. 유통레벨 콤보(제조/총판/대리점/일반유통): 없음. 유사한 건 취급상품별 공급유형 콤보인데 값이 다름(유통/제조/총판/없음). '대리점'·'일반유통' 값 자체가 코드에 없음. IMK 설정의 supplier_fields.distribution_level은 콤보가 아니라 텍스트 커스텀 필드.
  4. 취급상품 칸 삭제: 삭제 안 됨(등록/수정폼·엑셀업로드에 그대로).
  • 근본: IMK는 SG명·유통레벨을 **협력사 레벨 속성(콤보)**으로 두고 취급상품 목록은 없애길 원함. 현재는 반대로 취급상품(supplier_items)에서 카테고리·공급유형을 파생하는 모델. → 데이터 모델 전환이 필요한 작업.

§20. 결렬 사유 상시 노출·필수 — 검증 완료

  • agent의 모든 실패 경로가 단일 step "협상실패"(chat_end)로 수렴 → backend가 rejectRSP/CM로 무조건 매핑 → 프론트 통일 RejectForm(사유 필수). 세션 상태 분기 없음.
  • 실데이터: 협상거부(status=5) 9건 전부 reject_reason 존재, 사유 없는 결렬 0건.
  • 원 버그의 "견적마다 상이"는 대화 중 결렬(사유 있음) vs 미참여/마감 자동종료(대화 자체 없음 → 사유 없음)의 구분이었을 뿐, 결렬 플로우는 일관됨.

§21. 카드 3회 초과 — 정상 동작(버그 아님)

card_count=3은 협상카드 사용 한도다. 와일드카드와 최종제안(종결)은 이 한도와 별개로 각각 붙는 구조라, 공급사가 보는 카드가 3장을 넘을 수 있다.

  1. 와일드카드 1장(1% 인하/동적 카운터) — 협상카드 카운트와 별개.
  2. 최종제안 1장(중간값 절충/최후통첩) — 카드 소진 후 마지막 국면에 별도로 붙음. → 협상카드 3 + 와일드 1 + 최종제안 1 = 최대 5장 노출(예: EST-202607-4DB5).
  • 참고(엣지): 세션에 견적세팅(card_count)이 연결 안 되면 한도가 안 걸릴 수 있으니, 설정이 항상 세션에 물리는지만 확인.