Commit Graph

47 Commits

Author SHA1 Message Date
a5fa44ee25 [refactor] negodata/backend: QuotationService 파사드 분할 — services/quotation/(pricing·build·closing·queries·invites), 시그니처·임포트 경로 외 동작 무변경 2026-07-27 16:15:19 +09:00
7b612824be [refactor] negodata: 목표가 산정 정리 — purchase_only 죽은코드 제거(백+프론트)·산정 재료 로더 공용화·자동재생성 잔재 주석 정정 2026-07-27 16:07:21 +09:00
b539e073cb Merge commit 'dc8c288f' — lps-admin 신설·LPS 운영기능(ip_session/alerts/admin API)·최저가 출처링크 반영 2026-07-24 15:30:36 +09:00
51d07bb779 [feat] negodata: 재협상 소유권 게이팅·처리담당자·상세 링크·재생성 타이틀·알림 토스트(읽음API)·재협상요청 표기·커스텀필드 select 2026-07-24 14:18:52 +09:00
cfee6e89d0 [feat] negodata: 권한 3단계(개발자 신설)·개발자 메뉴 그룹·디자인 시스템 페이지
- UserRole 1=일반 2=최고관리자 3=개발자(내부 운영). 개발자 계정은 회원 목록·총계에서 제외해 고객사에 노출하지 않음
- 계정 생성 시 권한 선택(일반/최고관리자) 추가, 개발자는 앱에서 부여 불가(DB 시드 전용)
- 사이드바 '개발자' 그룹 신설 — 회사 설정·디자인 시스템을 개발자에게만 노출
- /dev/design 디자인 시스템 페이지: 색 토큰·타이포·버튼·배지·입력·반경, 목록 화면 구조, 반응형 기준, URL 상태 규칙, 회사 커스터마이징 훅
- 공급사 재협상 요청(#15) 플로우 문서 — sessions.custom 기반(DDL 0)
2026-07-23 15:41:36 +09:00
0f10b6a70f [feat] negodata·공급사포털: 상품 필드 숨김 설정·용어 카탈로그 확장·로그인 전 브랜딩·모바일 대응
- 회사 설정 hidden_fields 신설: 상품 목록·등록폼·엑셀 양식에서 감추고 목표가 후보에서도 제외
- 용어 카탈로그 9→37개(상품·협력사·견적 그룹), 목록·폼·엑셀 헤더 배선
- 엑셀 '최저한도' → '인터넷 최저가' 표기 정정(구양식 헤더는 alias 유지), 공급사 컬럼 검증 유지
- 목표가 산정내역에 적용 모드·숨김 필드 반영, 목표가 상한 라벨에 산식(상품단가×2) 표기
- 공급사 포털: 초청 링크 session_id 로 로그인 전 회사 브랜딩 조회(무인증 엔드포인트), 기본 브랜드 negotium 워드마크, negotium·AI O2O 크레딧 표기
- 목록 테이블 뷰포트 기준 전환·툴바 줄바꿈·협상현황 카드뷰로 모바일/태블릿 대응
- 이용안내 FAQ 탭 추가, 이용안내·회사설정 탭 URL 쿼리 동기화 및 빠른이동 등록
2026-07-23 11:29:35 +09:00
03322d6ca3 [feat] negodata: 카드 성공률 순위·상품 엑셀 TO-BE 싱크·회사설정 JSON 입출력·목록 포털형 UI
- 협상카드 성공률(사용 세션 대비 타결) 집계 추가, 견적 생성 카드선택 순위 정렬·통계 TOP5
- 상품 엑셀: 품목코드·모델명 라벨화, 리드타임 suffix 제거, 공급사 컬럼 신설(등록 후 supplier_items 매핑)
- 설정 화면 JSON 불러오기/내보내기(빈 값은 미갱신), IMK 설정 JSON 보관
- 설정·회원 페이지 새로고침 forbidden 수정(자식 loader 가 initAuth 대기)
- 협력사·견적 목록도 포털형 카드(툴바+테이블 결합)로 통일
2026-07-22 17:27:23 +09:00
88edcfed63 [feat] negodata: 회사 커스터마이징(설정·라벨·커스텀필드·엑셀·상품공급사#20·분류카테고리#17)·일괄삭제·로그export·구분·카드 전체선택·부가정보 표시 2026-07-22 15:20:24 +09:00
e8d2acaade [feat] negodata: 통계 인상억제율(재협상)·월별 차트 — 직전 라운드 투찰가 대비 인하율 파생 집계 2026-07-22 15:19:14 +09:00
민헌
4a20194dc8 feat(negodata): 인터넷 최저가 출처·링크·가격 추이 UI — 검증 가능한 협상 근거
인터넷 최저가는 견적 목표가·협상 카드(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>
2026-07-10 17:10:00 +09:00
민헌
28b4a9e797 feat(negodata): lowest-price 스텁 API 실구현 — 즉시 트리거 + 온디맨드 동기화 조회
- POST /v1/item/{id}/lowest-price: 상품 1건 LPS 즉시 검색요청(manual
  우선순위). queued/duplicated/unavailable 상태 반환, 실패는
  ErrorType.LPS_UNAVAILABLE(2000 블록 신설)
- GET /v1/item/{id}/lowest-price: 대표 최저가 + 최근 수집 이력(최신순,
  LowestPriceEntry 타입화). 조회 전 lps_db 증분 동기화 1회 수행 —
  5분 크론을 기다리지 않는 실시간 폴링 UX(멱등·저비용)
- 동시성 방어 2겹: 프로세스 내 asyncio.Lock(크론·온디맨드 직렬화) +
  uq_iilp_item_crawl_time 유니크 인덱스(alters/2026-07-10, init.sql
  멱등 반영·dev DB 적용) — 경합 진 쪽 tx 실패 후 다음 tick 흡수
- LpsSyncService 무인자 생성자(FastAPI Depends 호환)
- compose: negodata-backend 에 LPS_DB_HOST·LPS_BASE_URL env(미설정 시
  연동 비활성으로 조용히 동작)

검증(도커 컨테이너 e2e): 인증→POST queued→LPS 크롤→GET 온디맨드
동기화로 이력 즉시 노출(not_found 정책: 대표값 미변경 확인),
company 스코프 차단(타사 상품 ITEM_NOT_FOUND) 확인

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-10 16:17:05 +09:00
7f1c0be2b3 [feat] negodata: 협력사 채팅 계정(supplier_users) 관리 — 발급·비번 재설정·활성상태
- 백엔드: supplier_users/supplier_user_tokens ORM 매핑, /v1/supplier/{id}/account 4종(조회·발급·재설정·상태), 회사 스코프 게이팅, 재설정·비활성 시 토큰 삭제로 기존 로그인 즉시 무효화
- 비밀번호: 발급=서버 자동생성(1회 반환), 재설정=커스텀 지정 가능(미지정 시 자동생성)
- 프론트: 협력사 상세 SupplierAccountManager 섹션 + 목록 '채팅 계정' 컬럼, orval 재생성(SupplierType 은 enumLabels 로컬 상수로 이동)
- 테스트: test_supplier_account.py 9건, 전체 스위트 green
2026-07-10 10:14:00 +09:00
1b9ca062f3 [feat] negodata: 협상카드 회사 스코프·공용 읽기전용 + 견적 목표가 산정내역 수정
협상카드
- 목록/조회를 등록자 개인 → 회사(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
2026-07-09 17:04:40 +09:00
d21e7c10b0 [refactor] 공급유형 기준을 상품-협력사 매핑으로 전환 2026-07-07 17:05:07 +09:00
c62b66e35b [feat] negodata: 소유권 게이팅 + 견적 낙찰 + 작성자명 표시 + 전화입력 + 카드 엑셀
- 소유권 게이팅(common/authz): 변경 액션 본인∪OWNER, 협력사 삭제 OWNER 전용
- 견적 수동 낙찰(award) + 작성자명(creatorName) 표시 + 전화번호 입력 컴포넌트 + 카드 엑셀 업로드
- supplier_type 은 이번 커밋 미변경(다음 커밋에서 코드부터 정리 예정)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 16:18:33 +09:00
c32ee300e6 [feat] negodata: 통계 페이지(성과 분석) 추가 — 파생 집계 API + recharts 차트
- 백엔드 GET /v1/statistics/summary: 회사/내견적 스코프, 최근 6개월 파생 집계(저장 X, DDL 0)
- 지표: 총절감/절감률/낙찰률/앵커도달률/마감수/재견적라운드 + 월별추이·마감결과분해·참여율·유형별(협상/견적)·카테고리·카드빈도
- 프론트 recharts+shadcn Chart, 사이드바 통계 nav, /statistics

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 16:18:33 +09:00
43dbcbcd96 [feat] negodata: 협력사↔상품 매핑(취급상품·공급유형) + 견적 픽리스트 서버검색 콤보박스
- partner.supplier_items 매핑테이블 신설: supply_type(0없음/1유통/2제조/3총판), 부분 유니크 인덱스(soft-delete 인지). quotations.supplier_type와 의미단위 달라 컬럼명 supply_type.
- 백엔드: supplier_item CRUD/service/router(/v1/supplier-item, by-supplier·by-item·create·bulk·update·delete). 소유권 company 스코프. ErrorType.SUPPLIER_ITEM_NOT_FOUND 추가.
- DDL: 01-schema/04-alter(날짜접미 리네임) + dev DB 반영.
- 프론트(feature): 협력사 엑셀 '취급상품' 컬럼(콤마 상품명→일괄매핑, 이름 미매칭 스킵+리포트, 유형 안받고 없음), 협력사 상세 취급상품 관리(추가/삭제/유형변경 즉시반영), 견적모달 협력사 리스트에 선택상품 공급유형 배지.
- 재사용 서버검색 Combobox 신설 → 취급상품·견적상품·협력사초청·협상카드 픽리스트에 적용(size 100 캡 해소, 검색은 서버 ILIKE). 견적 선택상품 파생값은 useGetItem 단건조회로 안정화.
- orval 재생성(supplier-item 클라이언트/모델).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-07 09:59:13 +09:00
1ac42ddc9c [feat] negodata: 협력사 총매출액(total_revenue) 추가 + 우선선정(priority) 제거
Helped-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-06 17:27:59 +09:00
3176ec4262 Merge branch 'main' into feature/negodata
Helped-By: Claude Opus 4.8뀨 <noreply@anthropic.com>
2026-07-06 16:58:04 +09:00
38709b3098 [feat] negodata: 결렬 폐지→개찰 마감 개편 + 낙찰기준 견적 단위 이관 + 세팅 컬럼 정리 (백엔드+DB)
Co-Authored-By: Claude Opus 4.8뀨 <noreply@anthropic.com>
2026-07-06 16:36:00 +09:00
민헌
a2c299aa14 refactor(anchoring): 도메인 이름 전면 개편 — adjustments·anchoring_value/price·price_range·sample 용어 통일
용어 체계: 값=anchoring_value(정수‰)·가격=anchoring_price·조정=adjustment·구간=price_range·표본=sample

- DB: rate_adjustments→anchoring.adjustments (id→adjustment_id, price_bracket_index→price_range_index,
  nego_count→sample_count, anchor_rate_before/after→anchoring_value_before/after,
  consumed_session_ids→used_session_ids)
- sessions: target_anchoring_price→anchoring_price, anchor_rate_permille→anchoring_value,
  last_offered_price→last_offer_price, anchoring_adjustment_id→used_by_adjustment_id
- 뷰: rate_history/current_rates→value_history/current_values, delta_permille→value_change
- 코드: calc_price_range_index·calc_anchoring_price·evaluate_samples·get_current_value·
  get_latest_adjusted_value·get_current_anchoring_value·fetch_current_values·get_base_anchoring_value·
  Adjustment(ORM)·update_last_offer_price, 상수 ANCHORING_VALUE_MIN/MAX·ADJUSTMENT_STEP·
  PRICE_RANGE_COUNT/INDEX_MAX, 배치 로그 키 bracket=→price_range=
- API: negodata protocol 필드 target_anchoring_price→anchoring_price (front 생성 모델·컴포넌트 동반)
- 기존 DB 마이그레이션 신설: schedules/anchoring/migrations/20260706_rename_anchoring.sql
  (멱등 DO 블록 — 테이블·컬럼·뷰·인덱스·PK 제약. 코드 배포와 동시 적용 필요)
- postgres-init 01·04, 문서 6종 동기화
- 실배포 전 수정 포함: main.py argparse 화(--dry-run 단독·오타 플래그 기동 전 차단),
  박제 정합식 calc_anchoring_price 재사용, clamped 지표가 실제 포화만 집계(경계값 유지 제외)

주의: sessions.anchoring_value(정수‰)와 quotation_settings.anchoring_value(구 float 비율)는
같은 이름·다른 단위 — 구 컬럼은 미변경.

검증: 모듈 20·negodata 50·backend 57 테스트 통과, front tsc·vite build 통과,
로컬 DB 마이그레이션 적용 후 배치 dry-run·상주 기동·양 서버 부팅 확인.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 11:17:01 +09:00
e23349c11e [feat] negodata: 마감 close_reason 개편 + 견적상세 단가조정 스펙트럼
- 마감사유 quotations.close_reason(SMALLINT, 8종) 신설 — 낙찰/재협상3종/유찰4종 구분, 재생성 한도 카운팅. quotation_settings 에 mid_action·over_action·regen_limit(3구간 가격정책) 추가. models.py·enums.py·01-schema.sql·crud·service·테스트 정합.
- 프론트 노출: CloseReason/PriceGateAction 라벨·배지, 목록 마감결과 컬럼, 견적세팅 모달 3구간. orval 생성모델 갱신.
- 견적상세 결과밴드: 목표가→낙찰가→절감 stat 트리오를 단가조정 흐름 스펙트럼(목표가·최저·최고 투찰가)으로 교체. lowestBid/highestBid 는 bid_price 파생(DB 컬럼 아님), 최초가 컬럼 없어 시작앵커=최고 투찰가로 대체. 라벨 방향 값순 번갈아 배치로 겹침 방지.
- 라벨 정정: "단독 낙찰"→"낙찰"(낙찰은 단수), "목표 대비"→"목표가 대비".

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-03 08:37:40 +09:00
f19c6f57ea [chore] negodata: enum 주석 영문값 보강 + 견적상태 3종 정리 + 대시보드 정비
- enum DDL 주석에 영문값 보강(status/role/delivery/usage_type/qt_type/supplier_type)
- 견적상태 3종(생성/진행중/마감)으로 정리(ON_HOLD 제거), 배송 PARTNER→SUPPLIER
- 대시보드 손질, 관련 테스트·negosium 견적유형 주석 동반

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 17:25:38 +09:00
1d111a031e [feat] negodata: 알림함 — 견적 마감 결과(낙찰/재생성/결렬) 자동 통지
- company.notifications 테이블 + NotificationType(SUCCESS/REGENERATED/FAILURE)
- 백엔드 알림 조회/읽음 API + close_and_decide 결과 분기마다 알림 생성
- 헤더 알림 벨(안읽음 배지) + 알림 페이지(읽음·딥링크)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 17:24:59 +09:00
b42cc41b5e [feat] negodata: 대시보드 — 회사/내 견적 요약 API + 프론트 페이지
백엔드: GET /v1/dashboard/summary — 회사 전체(company)+내 견적(mine) 스코프로 진행중·이번달생성·마감임박(72h)·메일미발송·동가·결렬 집계(users.company_id 조인, 읽기 전용). 프론트: /dashboard 페이지(KPI 카드 + 액션 위젯, 행 클릭→/quotation?detail= 딥링크), 사이드바·라우트 배선, 루트·로그인 리다이렉트를 /dashboard 로. orval 재생성(useGetDashboardSummary + Dashboard* 타입, QuotationData.creator_name 동기화 포함).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 11:01:38 +09:00
5f648965e2 [fix] negodata: 견적 회사 스코프 적용 (목록·단건·세션 IDOR 차단) + 거짓 주석 제거
quotations 에 company_id 컬럼이 없어 견적 조회가 회사 무관하게 전부 노출되던 멀티테넌트 누수를 차단. 작성자(user_id)→users.company_id 서브쿼리로 회사 스코프를 걸어 목록(/list)과 단건·세션·협력사 엔드포인트(_fetch 가드)에서 남의 회사 견적을 NOT_FOUND 처리. 스케줄러/내부 호출은 company_id 없이 우회. 라우터/서비스의 '회사 스코핑 안 함' 거짓 주석 정정.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-30 11:01:27 +09:00
7b7a37ee98 [feat] negodata: 견적 목록 작성자 컬럼·내 견적 필터 + 검색바 클리어(X) 버튼
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-30 10:07:46 +09:00
33ce82997a [refactor] negodata: 목표가 산정내역을 백엔드 /target-breakdown 엔드포인트로 이관
- 생성(_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>
2026-06-30 08:40:30 +09:00
019f3dbeac [feat] negodata: 견적 목표가 산정 개편 + 협상 초청메일 + 카드 사용구분
[견적·목표가]
- 목표가 산정 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>
2026-06-29 13:33:08 +09:00
a40257ddc1 [feat] negodata: 회원관리 / 최고관리자(OWNER)
- OWNER 권한 신설, 최고관리자가 자기 회사 소속 직원(USER) 계정 생성·수정·삭제 관리
- 회사 사용자 API(/v1/company/user/*), 회원관리 페이지·폼
- 로그인/프로필 흐름 정비, 무인증 계정생성(/auth/create) 제거

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 13:31:32 +09:00
103c80046e [feat] negodata: 신규 견적유형 + 목표가·앵커링 산정 + 협력사유형 + 협상카드 용도
- 견적유형 4종: QuotationType 에 신규협상(3)·신규견적(4) 추가(1·2 재 고정)
- 목표가 산정: items(매입가·판매가·인터넷최저가) + quotations.md_price +
  quotation_settings.internet_average_fee 로 _calc_target_price(KTC 이식, 신규/재 분리),
  세션 target_price·target_anchoring_price 저장
- 협력사유형: quotations.supplier_type(SupplierType) + 직전유형 조회 API(/supplier/{id}/last-type)
- 협상카드 용도: nego_cards/wild_cards.usage_type(CardUsageType: 공통/신규견적전용/재견적전용)
- 스키마(01-schema.sql)·ORM·protocol·service·crud·프론트(생성타입/폼) 일괄, /backend enums·models 미러

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 17:09:14 +09:00
7f948075e5 [feat] negodata/backend: 견적 자동마감 스케줄러 + 다음 라운드 재생성(자동/수동)
- APScheduler 크론(KST 5분): 마감일 지난 견적 / 모든 세션 종결 견적 → close_and_decide
- 마감 판정: 단독 최저가 낙찰 확정 / 동가·전원미참여 다음 라운드 재생성 / 거부·한도 마감
- 재생성: 같은 견적번호 체인(round+1, 이름 '(N차)'), 공급사 수로 재협상·재견적, 사유별 한도(미참여1+동가1)
- 수동 재생성 POST /regenerate/{qt_id} (마지막 차수만 허용)
- CloseOutcome enum + 잡 결과별 로그

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 16:36:22 +09:00
d47476dc04 [refactor] negodata/backend: 서비스 계층 입력을 dict→타입드 Req 패킷으로 통일
라우터가 req.model_dump(exclude_unset=True)로 dict를 만들어 넘기던 것을
req(Req_*) 객체 그대로 전달하도록 변경. 서비스 시그니처를 전부 타입드로 통일.

- create 5개(quotation/card/item/supplier/quotation_setting): ORM은 명시 kwargs
  조립(item만 컬럼 16개라 model_dump 펼침). 경계 검증·타입 유지, **data 결합 제거.
- update 4개: 서비스가 req 받아 내부에서 model_dump(exclude_unset=True) 생성 후
  CRUD(dict)로 전달 — 공식 PATCH 메커니즘 유지.
- 서비스 계층 data: dict 시그니처 0개. CRUD는 dict 유지(의도).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 09:27:04 +09:00
eb6612af1c [refactor] negodata: 도메인 코드값 enum 정비 — 백엔드 정본 + 프론트 생성타입 사용
- 백엔드: 도메인 enum CodeEnum 상속(x-enum-varnames) → orval이 이름 있는 enum 생성. 응답 필드 enum 타입 지정(요청은 int 유지). ENUM_LABELS/DOMAIN_ENUMS·/v1/enums 제거
- 프론트: 생성 enum + 라벨맵으로 교체(매직넘버·발명 어휘 제거), 견적·세션 상태 코드화, role/delivery 라벨 프론트 소유
- 동반 정리: unwrap 캐스트·목업(buildSessions·데모)·死코드 제거, mapItem toMinPrice dedupe

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-22 17:06:26 +09:00
6fa024137f [feat] negodata: 견적·카드 검색/필터 서버사이드 전환 + 견적 상세 Sheet 리팩터
- 백엔드: quotation 목록 search 파라미터(name/number ILIKE) 추가; card 목록 is_wildcard 탭 필터 + total_nego/total_wild 탭 카운트 추가; status/type 코드 int 비교 보정
- 프론트: cards/quotation 검색·상태·유형 필터·페이지네이션을 useServerList 기반 서버사이드로 전환; 엔터 즉시검색 + 디바운스 500ms·최소 2글자; 죽은 client 필터 훅(useCardFilters/useQuotationFilters) 제거
- generated 파라미터/응답 타입 손보강(listCardsParams.is_wildcard, listQuotationsParams.search, resCardList.total_nego/total_wild) — orval 재생성 시 동일
- 견적 상세 Drawer→Sheet 분리, useOverlayParams→useOverlayRouter, CreateQuotationWizard→QuotationCreateModal

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-19 17:03:53 +09:00
088c57f415 Merge branch 'main' of https://gitea.o2o.kr/Negosium/o2o-negosium
# Conflicts:
#	postgres-init/03-seed-negodata.sql
2026-06-18 17:53:03 +09:00
4f0e4c29ce [feat] negodata: 견적목록 상품조인 + 견적/카드 페이지네이션 + 견적중단 서버연동 + 발의→등록
- 견적 목록에 대표 상품(세션 item) 조인 노출 → '대상 상품 확인 불가' 해소
  (backend protocol/crud/service + orval 재생성 + front mapQuotation 매핑)
- 견적·협상카드 목록 클라이언트 페이지네이션 추가 (useClientPagination)
- 견적중단을 서버 stop_quotation 호출로 영속 처리(상태=견적마감)
- 신규 협상견적 라벨 발의→등록 통일
- 발의 위저드 카드선택에 협상/와일드 구분 뱃지 추가

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 17:46:18 +09:00
f924c0aa59 Merge branch 'main' of https://gitea.o2o.kr/Negosium/o2o-negosium 2026-06-18 17:05:24 +09:00
b0b787a8ce cors 문제 해결 . 2026-06-18 16:30:03 +09:00
df68609c49 [feat] negodata/backend: 견적 협상대화에 사용 협상카드 내용 노출
QuotationCardData 에 number/edit_script/condition/memo 추가, card 카탈로그(nego/wild)
라이브 조인으로 채움. DB 컬럼 변경 없음(기존 카드 테이블 조인만 확장).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 16:21:58 +09:00
3280cab088 [feat] negodata/backend: 상품 이미지 업로드(Azure Blob) 엔드포인트 추가
POST /v1/item/image — SAS 토큰을 URL에 붙여 httpx PUT 으로 Azure Blob 업로드.
이미지 타입/용량 검증 + IMAGE_* 에러코드. config 에 azure_blob_base_url/sas/root 추가.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 16:21:58 +09:00
92047c2b79 [chore] negodata/backend: 미구현 엑셀 일괄등록(upload-excel) 스텁 엔드포인트 제거
item/supplier 의 POST upload-excel 스텁 라우트와 Res_ExcelUpload 프로토콜 제거.
프론트 엑셀 모달은 클라이언트 CSV 파싱+check-codes/create 로 도는 독립 기능이라 영향 없음.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 11:49:20 +09:00
e7660b10ac [feat] negodata/backend: 카드 도메인 CRUD 추가 + 견적·auth 보강
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 11:00:15 +09:00
1fef405e88 [feat] negodata/backend: 상품·협력사 목록 서버 페이지네이션 + 검색/필터(카테고리·priority) + 상품 카테고리 distinct 엔드포인트
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-18 11:00:15 +09:00
1f778ab975 [feat] negodata/backend: 상품·협력사·견적 도메인 CRUD + delivery_type 코드화 + 공용 /v1/enums
- item/supplier/quotation/quotation_setting CRUD·service·router 추가
- item protocol delivery_type str→int (ERD/스키마 SMALLINT 일치)
- DeliveryType enum + 한글 라벨, 공용 GET /v1/enums (도메인 코드 메타데이터)
- CompanyBrief → CompanyData 로 *Data 네이밍 통일
- CORS: WebServerConfig.client_url(단일) 도입 (config_models/router)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 15:58:38 +09:00
212725e5f9 [chore] 추적된 .pyc 제거 + 루트 .gitignore 추가
backend/__pycache__ 등에 추적되던 .pyc 51개를 인덱스에서 제거하고,
루트 .gitignore(__pycache__/, *.py[cod], .venv/, openapi.json, CLAUDE.md)를 추가한다.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-17 08:39:39 +09:00
ebfa7a15bb requirement.dev.txt 삭제 . 2026-06-15 15:58:06 +09:00