# IMK 0803 가격협상 요청 정리 원본: `0803_가격협상 우선 적용 및 논의 정리.xlsx` (12건). 시트의 `우선/논의` 구분 대신 **스펙이 확정돼 바로 착수 가능한 것 / 결정이 있어야 착수 가능한 것**으로 다시 갈랐다. 시트와 다른 3건 — ⑪은 수정으로, ③은 논의로, ④는 코드가 아니라 회사설정으로. --- ## 수정 (스펙 확정) ### ④ 부가세 입력칸 — 코드 문제 아님 `vat_yn` 은 상품폼(`ProductFormSheet.tsx`)·업로드 양식(`ExcelUploadModal.tsx`) 둘 다 이미 있다. IMK 회사설정이 `hidden_fields = [made_in, delivery_fee_yn, selling_price, vat_yn]` 라 화면·양식에서 같이 빠진 것. 설정에서 체크 해제하면 끝. ### ⑥ 유의사항 문구 / 헬프데스크 - 유의사항의 VAT·배송비 문구는 `GuideContent.tsx` 에서 상품별 동적 표기로 이미 바뀐 상태 → 요청대로 삭제. - 헬프데스크 연락처 실사용처 3곳, 전부 placeholder였음: `frontend/src/features/chat/components/menu/Contact.tsx`, `frontend/src/features/chat/components/popup/GuideContent.tsx`, `frontend/src/pages/LoginPage.tsx`. 초청 메일엔 없음. - **반영**: `companies.settings.branding.helpdesk: string[]` 로 회사별 설정화. 아래 "헬프데스크 배선" 참조. ### ⑦ 공급가–매입가 일원화 목표가 후보엔 이미 공급가가 없다(internet·purchase·selling — `pricing.py`). 잔여 2건: 1. 화면의 공급가(`item.price`, IMK 라벨 "공급가") 노출 제거 2. 신규 견적이 아직 인터넷최저가만 씀 → 매입가 후보 추가 ⚠️ **`items.price` 를 hidden 으로 감추면 안 된다.** `hidden_fields` 는 목록·등록폼·엑셀양식 3곳을 동시에 감추므로 신규 상품의 `price` 가 NULL 로 쌓이고, 협상 멘트의 인하율이 통째로 빠진다. `items.price` 소비처 → `items-price-is-nego-baseline` 메모 참조. ### ⑫ 시장가 산식 `(상품가+배송비)/1.1` 인터넷 최저가는 몰 판매가(VAT 포함·배송비 별도)로 수집되는데 우리 매입가·공급사 견적가는 VAT 별도라 축이 어긋난 채 비교 중. 배송비를 더해 실구매 총액을 만들고 1.1로 나눠 VAT를 벗긴다(약 9% 낮아짐). 미결 2개: - 배송비를 대부분 모른다(네이버 쇼핑 API 미제공, 실측 39/39 null). 0으로 칠지 / 미상이면 환산 스킵할지 - 적용 범위 — 카드 멘트 인용값만인지, 목표가 후보(`internet × (1−수수료율)`)에도 거는지. 후자면 인터넷 기준 목표가가 9% 내려간다. ### ⑪ 인터넷최저가 ≥ 목표가 → 시장가 카드 차단 (절반 완료) 견적생성 시 선택 게이팅은 반영됨(`useCardGating.tsx`). 잔여 = 협상 진행 중 런타임 차단. ### ⑤ 상품 일괄등록 유효성 오류 재현 케이스(어느 필드가 오탐인지) 확보 후 수정. 엑셀 원본을 받는 게 빠름. ### ② 목표가 초과 낙찰 허용 상한 그릇은 들어감(`sessions.done_ceiling_price`, 커밋 91b8dc77). **협상 엔진이 아직 안 읽는다** — `agent/`·루트 `backend/` 어디에도 `done_ceiling` 참조 없음. 타결 판정에 배선하면 EST-202607-973E 케이스 해소. 조건: 기존 단가 > 견적가 > 목표가 > 앵커링가면 타결. 여기서 "기존 단가" = `items.price`. --- ## 논의 (결정 필요) ### ③ 중간값 로직 ②의 짝. "목표가 초과 제시 안 함" 상한을 푸는 건 맞는데 **대신 무엇을 상한으로 쓸지** — `done_ceiling_price`(목표가×(1+율))인지 기존 단가인지. IMK 예시(목표 39,800 / 필요 40,200)는 +1.0% 수준이고 현 기본율은 +5%. ### ⑧ 세팅 횟수만큼 카드 소진 목표가에 이미 근접했는데도 남은 카드를 다 태울지. 라운드가 늘면 결렬 위험·시간도 는다. "최소 사용 횟수 보장" vs "조기 타결 우선" 중 택. ### ⑨ 앵커 제안가 단조성 후속 카드 제안가가 앞 카드보다 낮아지는 건(16,980 → 16,810) 카드마다 고정 인하율을 쓰기 때문. 제안가를 카드가 아니라 **라운드에 종속**시켜 단조 상향으로 바꾸는 구조 변경 → 이 중 유일하게 범위가 큼. ### ⑩ 와일드카드 + 최종제안 중복 종결 국면은 현재 **필수 관문**이다(`chat_engine.py` `check_iteration_limit`): 1. `closing_played` false → `force_closing` → 종결 전용 와일드카드 또는 폴백 최후통첩(목표가 제시) 2. `closing_played` true → 제시가 ≤ 목표가면 타결, 초과면 결렬 스킵하면 마지막 우리 카운터가 안 나가고 공급사 마지막 제시가로 즉시 판정 → **결렬률 상승**. 구현 시 `closing_played = True` 는 반드시 세워야 무한루프를 피한다. 단 중복 방지는 이미 양쪽에 걸려 있다 — 진입 단계(`chat_engine.py`)도 종결 단계(`chat_service.py`)도 `is_played` 로 쓴 카드를 건너뛴다. 코드상 같은 카드가 2회 나올 수 없으므로 IMK가 본 것이 진짜 동일 카드인지 확인이 먼저(dev DB엔 EST-202607-5947 없음 — 운영 데이터). ### ⑬ SG별 앵커링 **SG = `items.category`** (IMK 라벨 "SG명"). 현재 SG는 앵커링에도 목표가 산정에도 안 들어간다. 앵커링 축은 3개 — `(company_id, supplier_type, price_range_index)`: | 축 | 값 | |---|---| | `company_id` | 회사 | | `supplier_type` | 1 유통 / 2 제조 / 3 총판 — 개별 협력사가 아니라 **유형** | | `price_range_index` | 목표가 기준 46개 자릿수 구간 | SG 축을 추가하면 셀이 46×3×SG수로 쪼개져 셀당 표본 10건(`SAMPLE_THRESHOLD`)을 못 채우고 평가가 스킵·이월되어 **학습이 사실상 멈춘다**. 이게 실제 결정 포인트. --- ## 헬프데스크 배선 (⑥ 반영분) `companies.settings.branding.helpdesk: string[]` — 한 줄 = 담당자 한 명, 자유 문자열. | 경로 | 파일 | |---|---| | 편집 UI | `negodata/front/src/features/settings/SettingsView.tsx` (브랜딩 탭) | | 타입 | `negodata/front/src/features/settings/catalog.ts` | | 로그인 후 전달 | `backend/services/auth_service.py` `me()` — `branding` dict 통째로 내려 자동 포함 | | 로그인 전 전달 | `backend/services/auth_service.py` `session_branding()` + `protocol.py` `Res_SessionBranding` | | 표시 | `frontend/` 의 `Contact.tsx` · `GuideContent.tsx` · `LoginPage.tsx` | 값이 비면 각 표시부는 연락처 줄을 렌더하지 않는다(placeholder 노출 금지).