Commit Graph

17 Commits

Author SHA1 Message Date
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
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
민헌
5f9dec66cc refactor(anchoring): DDL·compose 루트 통합 — postgres-init/05 신설, 모듈 schema.sql·docker-compose 제거
- postgres-init/05-anchoring-schema.sql 신설(02-learning-schema 스타일) — anchoring 스키마·
  adjustments·인덱스 2종(부분 인덱스 포함)·뷰 2종. sessions 컬럼은 01/04 소관으로 명시
- 루트 docker-compose.yml 에 anchoring + anchoring-redis 서비스 추가(기존 스타일),
  헤더 서비스 목록·DB 준비 절차 갱신, 모듈 compose 의 로그 로테이션(10MB×5) 이관
- 모듈 schema.sql·docker-compose.yml 삭제 — DDL 단일 원본은 postgres-init/05
- tests/conftest 부트스트랩 경로를 05 로 교체, 문서 4종·주석 포인터 갱신
  (인수인계의 낡은 'negodata 가 redis 참조' 문구도 무Redis 현실로 교정)
- 검증: 모듈 20·negodata 50 테스트 통과, docker compose config 정상

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 11:37:13 +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
민헌
b362edf0d7 feat(negodata): 앵커링 v1.2 적용 — 칸 rate 조회·정수 박제·재생성 앵커 상속 폐지
- common/anchoring 이식 패키지 신설: 원본(schedules/anchoring)에서 읽기 경로 발췌
  (constants·base_table·service) + reader 이식판(Redis 미사용 — current_rates 뷰
  단일 쿼리, 실패·무이력 시 정적 테이블 폴백으로 견적 생성 무중단)
- _build_quotation: 목표가 산정과 앵커 산출 분리 — 칸(items.company_id ×
  quotations.supplier_type × 가격구간) rate 로 tp*(1000-rate)//1000 정수 박제,
  anchor_rate_permille 동시 기록. quotation_settings.anchoring_value 계산 사용 중단
- 재생성(regenerate_next_round): target_price 만 상속, 앵커는 생성 시점 rate 재계산
  (인수인계 규칙 1 — 상속 폐지)
- sessions 모델 anchor_rate_permille 매핑, crud get_item_companies 신설
- 테스트 6종 신설(스키마 부재 폴백·칸별 조정 반영·유형 미지정·재생성 재계산·
  bracket 경계 골든 벡터) — 전체 스위트 50 통과
- negodata 담당자 승인 하 직접 적용. 6개월 압축 시뮬레이션(격주 배치 13회,
  세션 522건)으로 박제→소비→재박제 루프·클램프·이월·이중소비 방지 검증 완료

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-04 16:37:27 +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
82076e138e [test] negodata: 백엔드 테스트 스위트 구축 + 공통 픽스처(conftest) 정비
- test DB 세션마다 자동 create/drop (팀원은 Postgres만 있으면 pytest 한 방)
- auth_headers 시드 픽스처(무인증 /auth/create 제거 대응) + other_company_id
- 커버: 회사 스코프(견적·상품·협력사·대시보드·세팅), 견적 마감 재견적 O/X + 알림,
  견적 생성·목표가, 알림함 읽기, 회사유저 OWNER 게이팅, 기존 파일 검증/기대결과 주석 정비

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-01 15:06:55 +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
7e0f88ca03 [fix] 견적 자동마감 동시성·정합성 + 프론트 안정화 (코드리뷰 후속)
백엔드 close_and_decide 경로:
- 동시 이중 마감 가드: 마감 판정 전 원자적 CLOSED 선점(claim)으로 두 크론 잡·수동마감 경합 직렬화
- 재생성 실패 표면화: regenerate_next_round 결과 검사 → 실패 시 REGEN_FAILED 반환(체인 끊김 은폐 방지)
- 차수 충돌 방지: 다음 라운드 = 체인 최신 round+1(chain_max_round 기준)
- 재생성 사유 집계 정밀화: 미참여/동가를 양성 표식으로 구분(단독낙찰·거부 오집계 제거)
- 재생성 라운드 최소 협상기간 하한(즉시 재마감 캐스케이드 방지)
- 잡 루프 per-item 예외 격리(한 건 실패가 배치 전체를 멈추지 않음)

프론트:
- useChatController: 무권한 가드를 sessionId 별로 추적해 세션 변경 시 자연 해제
- useScrollLock: 마지막 해제를 rAF 로 지연해 재마운트 사이 일시적 잠금 해제 방지
- quotation 상세 쿼리 placeholderData 로 라운드 전환 중 시트 유지

테스트:
- 신규 test_close_and_decide_fixes.py(동시성·차수·집계·기간 하한 검증)
- conftest 결함 수정(존재하지 않는 tbl_account TRUNCATE 제거, companies.status 명시)
- stale 테스트 갱신(test_quotation_create 를 타입드 Req/신규 응답 형식에 맞게 재작성)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-25 17:22:21 +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
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