- agent: 인터넷 최저가(items.internet_lowest_price)를 협상 파이프라인에 연결
(nego_context_crud 조회 → context loader → session.context → chat_engine.vars_for).
값 있을 때만 {internet_lowest_price}/internet_min_price 치환, 미수집(0)이면 원형 유지(허위 시장가 방지)
- negodata: 카드 에디터 변수 카탈로그에 '인터넷 최저가' 추가
- negodata: 견적 생성 카드 선택 게이팅 — 조건전략 미작성({customer_condition} 잔존)·
최저가 미수집 상품의 {internet_lowest_price} 인용 카드는 선택 불가(상품 변경 시 자동 해제 포함)
- negodata: 상품 엑셀 업로드의 협력사 목록 size 1000→100
(PageParams le=100 초과 시 422 → 목록 비어 전 행 '미등록 협력사' 오탐)
- seed: WC-01 의 데이터 소스 없는 {customer_reference} 제거 → 고정 문구로 대체
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- UserRole 1=일반 2=최고관리자 3=개발자(내부 운영). 개발자 계정은 회원 목록·총계에서 제외해 고객사에 노출하지 않음
- 계정 생성 시 권한 선택(일반/최고관리자) 추가, 개발자는 앱에서 부여 불가(DB 시드 전용)
- 사이드바 '개발자' 그룹 신설 — 회사 설정·디자인 시스템을 개발자에게만 노출
- /dev/design 디자인 시스템 페이지: 색 토큰·타이포·버튼·배지·입력·반경, 목록 화면 구조, 반응형 기준, URL 상태 규칙, 회사 커스터마이징 훅
- 공급사 재협상 요청(#15) 플로우 문서 — sessions.custom 기반(DDL 0)
- 채팅 링크로 바로 진입하면 세션이 협상생성(1)에 머물러 오프닝 메시지가 seed 되지 않던 문제:
chat init/messages 에서 participate 와 동일하게 협상중(2)으로 전이(마감 견적·마감시간 초과는 제외)
- 부가정보 저장이 1301 로 실패하던 문제: '협상완료' 요약은 chat_end=false 라 세션이 아직 협상중이므로,
마지막 말풍선이 summaryRSP/CM 이면 협상중 세션도 저장 허용
- 채팅 언마운트 시 messages 캐시도 제거 — staleTime:Infinity 라 빈 목록이 남아 재진입해도 빈 화면이던 문제
- 채팅 스크롤을 컨테이너 기준 scrollTo 로 변경(rAF 후 실행) — 요약·폼이 뒤늦게 레이아웃되면 중간에 멈추던 문제
- 모바일 채팅 상단 여백 제거(pt-[64px] 는 우측 협상절차 카드가 있는 lg 이상만)
- 노치 대응: viewport-fit=cover + safe-t/b/x 유틸 신설, 헤더·하단 액션 덱·드로어·랜딩 헤더에 적용, h-screen→100dvh
- 회사 설정 hidden_fields 신설: 상품 목록·등록폼·엑셀 양식에서 감추고 목표가 후보에서도 제외
- 용어 카탈로그 9→37개(상품·협력사·견적 그룹), 목록·폼·엑셀 헤더 배선
- 엑셀 '최저한도' → '인터넷 최저가' 표기 정정(구양식 헤더는 alias 유지), 공급사 컬럼 검증 유지
- 목표가 산정내역에 적용 모드·숨김 필드 반영, 목표가 상한 라벨에 산식(상품단가×2) 표기
- 공급사 포털: 초청 링크 session_id 로 로그인 전 회사 브랜딩 조회(무인증 엔드포인트), 기본 브랜드 negotium 워드마크, negotium·AI O2O 크레딧 표기
- 목록 테이블 뷰포트 기준 전환·툴바 줄바꿈·협상현황 카드뷰로 모바일/태블릿 대응
- 이용안내 FAQ 탭 추가, 이용안내·회사설정 탭 URL 쿼리 동기화 및 빠른이동 등록
- 협상카드 성공률(사용 세션 대비 타결) 집계 추가, 견적 생성 카드선택 순위 정렬·통계 TOP5
- 상품 엑셀: 품목코드·모델명 라벨화, 리드타임 suffix 제거, 공급사 컬럼 신설(등록 후 supplier_items 매핑)
- 설정 화면 JSON 불러오기/내보내기(빈 값은 미갱신), IMK 설정 JSON 보관
- 설정·회원 페이지 새로고침 forbidden 수정(자식 loader 가 initAuth 대기)
- 협력사·견적 목록도 포털형 카드(툴바+테이블 결합)로 통일
- 상품 테이블 인터넷 최저가 셀: 값 옆에 차트 아이콘 버튼 상시 노출
(기존 hover 밑줄만으론 클릭 가능성이 안 보임) — 값 없는 상품도
버튼으로 진입해 빈 상태 안내를 받는다
- 상세 시트 재구성: 견적 상세 드로어와 같은 SectionCard 문법으로 통일
· 헤드라인 카드: 상품명 → 대표가(26px rose) + 단가 대비 칩
(절감=emerald·역전=amber, Trending 아이콘) + 단가·마지막 수집 캡션
· 최저가 출처: 섹션 타이틀 우측 사이트 배지, 링크는 outline 버튼화
· 가격 추이: 수집 횟수 캡션, 2회 미만이면 안내 문구(빈 영역 방지)
· 수집 이력: 배지 폭 고정(w-14)으로 컬럼 정렬, 링크 없는 행 자리 유지
검증: 헤드리스 렌더 확인(테이블 셀·시트 v2 스크린샷), tsc 통과
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
인터넷 최저가는 견적 목표가·협상 카드(NGC-008 시장가 근거)의 근거값
— "어디서 찾았는지"를 클릭 한 번으로 검증할 수 있어야 한다.
- 스키마: iilp 에 lp_name(찾은 상품명)·lp_url(판매 페이지 링크) 추가
(alters/2026-07-10-iilp-source-link.sql, init.sql 멱등 반영·dev 적용)
- 동기화: price_history 의 final_source 에 맞는 naver/coupang name·url
을 함께 반영(기존 행은 NULL 공존)
- API: LowestPriceEntry 에 lp_name/lp_url + orval 재생성
- UI: 상품 테이블 인터넷 최저가 셀 클릭 → 상세 시트
· 대표가(rose) + 상품 단가 대비 차액(절감=emerald/역전=amber)
· 출처 카드: 사이트 배지·찾은 상품명·판매 페이지 새탭 링크
· 가격 추이 라인 그래프(성공 수집 2건부터, recharts+ChartContainer
라이트/다크 쌍 — 통계 차트와 동일 문법)
· 최근 수집 이력 리스트(미발견 amber, 행별 외부링크)
검증: 실데이터 e2e(A4 재수집 → lp_name/lp_url 반영 확인) +
헤드리스 브라우저 렌더 확인(시트·그래프·툴팁·링크), tsc·build 통과
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- 가짜 setTimeout 애니메이션 제거 — 상품별 POST lowest-price(큐 접수,
duplicated 는 결과 대기 합류) 후 GET 5초 폴링(서버가 조회 시 lps_db
증분 동기화를 겸하므로 폴링이 곧 수집)
- 요청 시각 이후 crawl_end_time 이력만 이번 결과로 인정, 완료/미발견
로그 구분(emerald/amber), 5분 대기초과분은 주기 동기화 자동반영 안내
- 종료 시 /v1/item/list invalidate → 테이블 인터넷 최저가 컬럼 갱신
- 닫기 = 폴링만 중단(서버 검색은 계속됨을 UI 에 명시)
- orval 재생성: lowest-price 응답 타입화(LowestPriceEntry·lowest_price)
검증: tsc 통과, vite build 통과 (API 흐름 자체는 ③ e2e 로 검증됨)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
① 카드 목록 스크립트 미리보기에서 {변수} 토큰을 한글 라벨 칩으로 렌더
(renderCardScriptPreview) — 원시 토큰({prev_partner_price} 등) 노출 제거.
② "조건 전략"(customer_condition) 특수 변수 추가:
- 툴바 '+ 조건 전략' → 본문에 위치 칩 삽입, 본문 아래 별도 Slate 입력창 노출
- 조건 내용은 변수 노드에 중첩 보관(edit_script 배열 유지·하위호환) + 저장 시
script 의 해당 위치에 주입 → agent 는 완성된 문구를 그대로 읽음(무변경)
- 서브 에디터는 조건 전략 버튼 숨김(중첩 방지), 빈 조건 저장 차단
DB·백엔드·agent 변경 없음(edit_script 타입 unknown, 조건 노드 내 중첩).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
agent 전술 재설계로 늘어난 치환 변수를 편집기 툴바·칩에 노출:
제시가(input_price)·협력사 직전가(prev_partner_price)·제안가(counter_price)·
중간가(target_mid_price)·절충가(middle_price)·인하율(discount_rate).
name 은 agent chat_engine.vars_for 치환 키와 일치. 라벨은 렌더 시점 조회라
기존 저장 카드도 마이그레이션 없이 한글 라벨로 표기된다.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
협상카드
- 목록/조회를 등록자 개인 → 회사(company.users 조인) 단위로 확장: 같은 회사 유저 카드 + 공용(user_id NULL)
- 공용 카드는 기본 제공 자산 → 수정·삭제 불가(OWNER 포함), is_shared=True API 등록 거부
- 개인 카드 변경은 본인∪최고관리자만, 프론트 버튼 disable+툴팁
- 공개범위 셀렉터·엑셀 공개범위 컬럼·CardTable 전체 배지 제거(항상 개인 등록)
- test_card.py 5케이스 재작성
견적 목표가 산정내역
- get_setting_rates: 단일 컬럼 select 결과를 이중 인덱싱해 항상 예외 → 마진율이 늘 0으로 적용되던 버그 수정
- get_target_breakdown: 채택 후보 판정을 '현재 최소값' → '저장 목표가와 값 일치'로 변경(산정 후 상품가 변동에도 초록 체크 유지)
- 견적상세 협상카드 탭 세션ID 컬럼 제거
견적생성 모달
- 목표가 미리보기·마감기한 기본값(+1h)·미래 검증, combobox 팝오버 scrollIntoView, maskPrices 비율(%) 마스킹
Little-Helped: Stupid Claude
- 소유권 게이팅(common/authz): 변경 액션 본인∪OWNER, 협력사 삭제 OWNER 전용
- 견적 수동 낙찰(award) + 작성자명(creatorName) 표시 + 전화번호 입력 컴포넌트 + 카드 엑셀 업로드
- supplier_type 은 이번 커밋 미변경(다음 커밋에서 코드부터 정리 예정)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
표현 아키텍처: agent 스크립트는 의미(텍스트)만 소유, 표현(굵기·색)은 프론트 소유.
Slate 는 negodata 에디터 내부에만 두고, 전송/저장은 마커 문자열 한 벌(구버전의 리치텍스트 이중관리 폐기).
- 트랙 A (negodata): serializeToMarker 추가 — Slate 마크(bold/underline/color)를 **/__/{{토큰}} 로
인코딩해 nego_cards.script 저장. edit_script(Slate 원본)는 재편집 전용. 고정 3색 → 시맨틱 토큰(강조/안내).
- 트랙 B (agent): 카드 멘트 DB 소스 — ICardScriptRepository/CardScriptDbRepository(port+adapter),
ScriptRepository.resolve_card_script 가 cards.source_type=backoffice_db 면 card.nego_cards.script 우선,
없으면 파일 폴백. action_id→card_id→nego_cards.number 매칭.
- 트랙 C (양 프론트): renderEmphasis 재귀 파서 — **굵게**·__밑줄__·{{강조|빨강}}·{{안내|파랑}} 중첩 렌더.
색은 시맨틱 토큰→디자인 토큰 클래스(다크모드 안전). negodata tokens.css 에 --info 신설. CardTable 미리보기 적용.
- supplier_items 연동: 유통코드=supplier_items.supply_type(→quotations.supplier_type 폴백),
파트너유형=상품별 매핑 협력사 수(→세션 이력 폴백).
- 가격 수용률: 기존 공급가(item_price) 기준 양보율로 정정 — 첫 라운드부터 실값(첫 제시가 기준 0 아님).
테스트: agent 86/86, 공급사 frontend·negodata front tsc 통과.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- 견적 생성: 협력사 유형 전 유형 입력(항상 노출), 명칭 협상견적→견적, 단계 인디케이터 확대·클릭 이동, 라벨 통일
- 온보딩 가이드: 견적 유형 차이 안내 탭(목표가 산정·협력사 수, MD 제시가 우선 강조)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- 생성(_calc_target_price)과 표시(get_target_breakdown)가 _candidates 헬퍼를 공유
→ 프론트 재계산 제거, 저장된 목표가와 항상 일치
- TargetPriceModal: useGetTargetBreakdown 으로 후보·채택·앵커링가 '표시만'
- QuotationType.is_new() 한 곳에서 신규유형 판단(생성·산정 공통)
- enum 라벨 단일출처(lib/enumLabels.ts): 협력사유형/카드 사용구분/유저상태
members·CardFormSheet 는 거기서 re-export
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
[견적·목표가]
- 목표가 산정 KTC 기준 정비(MD 우선, 없으면 인터넷최저가·매입가·판매가 중 최저 / 신규는 인터넷최저가만)
- 인터넷 평균 수수료 0.078 상수화(견적설정 컬럼 제거)
- 앵커링가 세션 저장 + 목표가 클릭 시 산정내역 모달
- 재생성 시 목표가·앵커링가 재계산 없이 직전 값 상속(KTC)
- MD 제시가·협력사 유형(유통·제조·총판·기타) 입력
[협상카드]
- 사용 구분(공통/신규견적전용/재견적전용)
[협상 진행]
- 협력사 초청 메일 발송(일괄/개별·재발송, 발송상태 표시)
[기타]
- 견적상세 창 닫기 버그 수정, 불필요한 컬럼 주석 정리
- DB: 기존 DB는 postgres-init/04-alter.sql 적용 필요(자동 마이그레이션 없음)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>