o2o-negosium-original/negodata/backend/services
민헌 95086cb3f6 feat(negodata): 4단계 — 사용자 화면에서 '없음'과 '확인 못함'을 구분
마지막 단계. 차단당해 못 본 몰이 화면에서 '–'(없음)로 보여 사용자가 "쿠팡엔 더 싼 게 없구나"로
오해하던 문제를 끝낸다. 안 본 걸 없다고 말하지 않는다.

사용자 화면은 **셋으로 접는다**(lps/docs/result-states.md 3-2절). 할 수 있는 행동이
'쓴다/다시 시도/넘어간다' 뿐이라, 원인이 달라도 다음 행동이 같으면 같은 표기다:
  matched                            → 가격
  no_match · empty                   → '–'        (확인했고 없었다)
  blocked · env_blocked · unavailable → '확인 못함' (못 봤다)
운영자 화면(lps-admin)은 같은 데이터로 7상태를 그대로 본다 — 목적이 진단이라 접지 않는다.

체인 전체를 이었다:
- postgres-init/alters/2026-08-07-iilp-source-state.sql — item_internet_lowest_prices 에
  sources/partial 추가(멱등, **운영 적용 필요**)
- models.py / lps_sync_crud 읽기 계약 / lps_sync_service 미러링 / LowestPriceEntry 프로토콜
- orval 재생성(ORVAL_INPUT 으로 저장 스펙에서 — 서버 없이). 생성 diff 는 새 필드만.
- PriceUpdateModal: 가격이 없는 몰이 '못 본 몰'이면 '–' 대신 '확인 못함'.

partial 은 LPS 가 판단해 내려준 사실을 그대로 쓴다 — 화면이 '어떤 상태가 확인된 것인가'를
다시 판정하면 상태 정의가 LPS 와 negodata 두 곳으로 흩어진다.

E2E 검증(실 DB 2시나리오): by_mall 은 둘 다 naver 뿐인데 쿠팡 칸이 '확인 못함'(차단) / '–'(0건)
으로 갈린다. tsc 오류 없음(기존 xlsx 미설치 오류는 무관). negodata 97 · lps 292 passed.

> 폴더 관례상 negodata 는 인수인계 대상이나, 사용자 요청으로 이번 건도 예외 적용.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-07 11:21:56 +09:00
..
email_templates [feat] negodata: 초청 메일 헤더에 회사 브랜딩(settings.branding.email_header) 배선 2026-07-22 15:54:05 +09:00
quotation [feat] negodata: 타결 상한(done_ceiling) — 세팅 기본율%·견적 override·세션 박제, 견적생성 3단계 타결/낙찰 섹션 분리·재생성 상속 2026-08-04 08:56:03 +09:00
agent_notify.py [feat] 카드 카탈로그 DB 정본화 — config 결합 제거 + 학습 보존 자동반영 2026-07-08 14:56:28 +09:00
auth_service.py [fix] negodata: /me 응답 role 을 UserRole enum 으로 직렬화 (Pydantic 경고 제거) 2026-07-01 14:41:39 +09:00
azure_blob_client.py [feat] negodata/backend: 상품 이미지 업로드(Azure Blob) 엔드포인트 추가 2026-06-18 16:21:58 +09:00
card_service.py [feat] agent·negodata: 협상카드 전술 데이터화(tactic JSONB·스크립트 파싱) + 발동규칙 정비 2026-08-05 11:48:14 +09:00
company_settings_service.py [feat] negodata: 회사 커스터마이징(설정·라벨·커스텀필드·엑셀·상품공급사#20·분류카테고리#17)·일괄삭제·로그export·구분·카드 전체선택·부가정보 표시 2026-07-22 15:20:24 +09:00
company_user_service.py [feat] negodata: 권한 3단계(개발자 신설)·개발자 메뉴 그룹·디자인 시스템 페이지 2026-07-23 15:41:36 +09:00
dashboard_service.py [chore] negodata: enum 주석 영문값 보강 + 견적상태 3종 정리 + 대시보드 정비 2026-06-30 17:25:38 +09:00
email.py [feat] negodata: 초청 메일 헤더에 회사 브랜딩(settings.branding.email_header) 배선 2026-07-22 15:54:05 +09:00
item_service.py [feat] negodata: 회사 커스터마이징(설정·라벨·커스텀필드·엑셀·상품공급사#20·분류카테고리#17)·일괄삭제·로그export·구분·카드 전체선택·부가정보 표시 2026-07-22 15:20:24 +09:00
lps_sync_service.py feat(negodata): 4단계 — 사용자 화면에서 '없음'과 '확인 못함'을 구분 2026-08-07 11:21:56 +09:00
notification.py [feat] negodata: 알림함 — 견적 마감 결과(낙찰/재생성/결렬) 자동 통지 2026-06-30 17:24:59 +09:00
quotation_setting_service.py [feat] negodata: 타결 상한(done_ceiling) — 세팅 기본율%·견적 override·세션 박제, 견적생성 3단계 타결/낙찰 섹션 분리·재생성 상속 2026-08-04 08:56:03 +09:00
renegotiation_service.py [refactor] negodata/backend: QuotationService 파사드 분할 — services/quotation/(pricing·build·closing·queries·invites), 시그니처·임포트 경로 외 동작 무변경 2026-07-27 16:15:19 +09:00
statistics_service.py [feat] negodata: 견적 목표가·앵커 반올림 + 통계 협상카드 효과 — 목표가=매입가×(1−네고율) 자동입력·산정후보를 낙찰기준탭으로 이동·목표가상한 상시표시 제거, 후보가/앵커 생성가 10원 단위 반올림(신규 세션, schedules 앵커와 동일 공식), 산정모달은 구매담당자 제시가 있어도 후보 전부 노출·MD입력가→구매담당자 제시가, 신규상품 등록에 공급사칸 추가, 상품상세/견적생성 라벨 회사설정 연동, 통계 협상카드 효과(유형별 사용빈도+사용직후 평균 제시가 하락)·와일드카드 1%인하 집계, mono 폰트 폴백 2026-07-29 09:51:03 +09:00
supplier_item_service.py [feat] negodata: 회사 커스터마이징(설정·라벨·커스텀필드·엑셀·상품공급사#20·분류카테고리#17)·일괄삭제·로그export·구분·카드 전체선택·부가정보 표시 2026-07-22 15:20:24 +09:00
supplier_service.py [feat] negodata: 회사 커스터마이징(설정·라벨·커스텀필드·엑셀·상품공급사#20·분류카테고리#17)·일괄삭제·로그export·구분·카드 전체선택·부가정보 표시 2026-07-22 15:20:24 +09:00