모듈·backend·문서 3개 관점의 적대 리뷰에서 확인된 결함 일괄 수정: [모듈] - 배치에 company_ids 스코프 옵션 추가 — 통합 테스트가 공유 dev DB 의 실세션을 소비/마킹하던 문제 해소(테스트는 시드 회사로 한정), 표적 수동 실행 옵션 겸용 - Redis 방어: compose 포트를 127.0.0.1 바인딩(무인증 공개 차단), get_rate 에 범위([10,200]) 검증 — 오염 캐시값은 미스 취급 후 자가 교정, 미스 백필은 SET NX (배치가 방금 쓴 새 값을 구값으로 덮는 write-after-read 경합 방지) - 배치: Redis ping 후 re-SET(다운 시 셀×timeout 지연 없이 즉시 스킵), 스캔 조인 ON 절에 quotations/items deleted 필터(철회 거래를 학습에서 배제), 제외 마킹을 청크별 커밋(레거시 대량 첫 실행의 장시간 단일 트랜잭션 방지) - main: SIGTERM/SIGINT 핸들러(docker stop 시 정리 로직 보장), --once 부분 실패 시 종료코드 1(런북/cron 감지 가능) [backend] - finalize_session·update_last_offered_price 에 status=IN_PROGRESS 가드 — negodata 일괄마감/중복 전송 경합이 종료된 세션을 되살리거나 가격 흔적을 사후 변경하는 것 차단(파생 판정 결정성 보호) - 신규 DB 부트스트랩: sessions 3컬럼을 postgres-init/01-schema·04-alter 에도 반영(backend 가 모듈 DDL 없이 기동) — anchoring 스키마 자체는 모듈 소유 유지 - 낡은 주석 정리(agent_client·quotation_settings 의 구 앵커 산출 서술) [테스트·문서] - 신규 테스트: 격주 게이트 골든(ISO 주차), supplier_type NULL, 가격 제시율 0% WARN — 모듈 18개·backend 57개 통과 - 문서 정합 감사 20건 반영: 잔존 33,334/노출 문구 제거, §10 SQL 을 실제 코드 (LEFT JOIN+deleted)와 일치, §11 자동/수동 검증 구분, FastAPI 오기 제거, 인수인계 reader 시그니처(db 인자), TODO 백로그 5건 기록 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
63 lines
4.7 KiB
SQL
63 lines
4.7 KiB
SQL
-- 기존 DB ALTER 누적 파일. 새 컬럼/변경은 이 파일에 계속 append 한다.
|
|
-- 전부 IF NOT EXISTS 라 몇 번을 재실행해도 안전(돌리면 최신 상태로 맞춰짐).
|
|
-- 신규/리셋 DB 는 01-schema.sql 에 이미 반영돼 있어 이 파일이 필요 없다.
|
|
|
|
-- ───────────────────────────────────────────────────────────
|
|
-- [2026-06-26] 견적 개편: 가격(매입/판매)·수수료율·앵커링가 + 견적/카드/협력사 분류 컬럼
|
|
-- ───────────────────────────────────────────────────────────
|
|
|
|
-- 상품: 인터넷최저가 실값 + 매입가 + 판매가
|
|
ALTER TABLE partner.items
|
|
ADD COLUMN IF NOT EXISTS internet_lowest_price BIGINT,
|
|
ADD COLUMN IF NOT EXISTS purchase_price BIGINT,
|
|
ADD COLUMN IF NOT EXISTS selling_price BIGINT;
|
|
|
|
-- 세션: 앵커링가
|
|
ALTER TABLE negotiation.sessions
|
|
ADD COLUMN IF NOT EXISTS target_anchoring_price BIGINT;
|
|
|
|
-- 견적: MD 제시가 + 협력사(공급채널) 유형
|
|
ALTER TABLE quotation.quotations
|
|
ADD COLUMN IF NOT EXISTS md_price BIGINT,
|
|
ADD COLUMN IF NOT EXISTS supplier_type SMALLINT;
|
|
|
|
-- 카드: 사용 범위 구분(CardUsageType): 1=공통 2=신규견적전용 3=재견적전용
|
|
ALTER TABLE card.nego_cards
|
|
ADD COLUMN IF NOT EXISTS usage_type SMALLINT NOT NULL DEFAULT 1;
|
|
ALTER TABLE card.wild_cards
|
|
ADD COLUMN IF NOT EXISTS usage_type SMALLINT NOT NULL DEFAULT 1;
|
|
|
|
-- ───────────────────────────────────────────────────────────
|
|
-- [2026-06-29] 협상 초청 메일: 세션별 발송 시각(수동 발송 버튼이 채움)
|
|
-- ───────────────────────────────────────────────────────────
|
|
ALTER TABLE negotiation.sessions
|
|
ADD COLUMN IF NOT EXISTS email_sent_at TIMESTAMPTZ;
|
|
|
|
-- ───────────────────────────────────────────────────────────
|
|
-- [2026-06-30] 알림(인박스): 협상 이벤트를 견적 작성자에게 통지
|
|
-- ───────────────────────────────────────────────────────────
|
|
CREATE TABLE IF NOT EXISTS company.notifications (
|
|
notification_id uuid PRIMARY KEY DEFAULT gen_random_uuid(),
|
|
user_id uuid NOT NULL, -- 수신자(company.users.user_id) = 견적 작성자
|
|
type SMALLINT NOT NULL, -- 알림 유형(NotificationType): 1=success(낙찰), 2=regenerated(재생성), 3=failure(결렬)
|
|
ref_qt_id uuid NULL, -- 관련 견적(quotation.quotations.qt_id)
|
|
ref_session_id uuid NULL, -- 관련 세션(negotiation.sessions.session_id)
|
|
data JSONB NULL, -- 렌더 스냅샷(유형별)
|
|
read_at TIMESTAMPTZ NULL, -- 읽은 시각(NULL=안읽음)
|
|
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
|
deleted BOOLEAN NOT NULL DEFAULT FALSE
|
|
);
|
|
CREATE INDEX IF NOT EXISTS idx_notifications_user_id ON company.notifications (user_id);
|
|
CREATE INDEX IF NOT EXISTS idx_notifications_user_unread ON company.notifications (user_id, created_at) WHERE deleted = FALSE AND read_at IS NULL;
|
|
CREATE INDEX IF NOT EXISTS idx_notifications_ref_qt_id ON company.notifications (ref_qt_id);
|
|
|
|
-- ─────────────────────────────────────────────────────────────
|
|
-- [2026-07-02] 앵커링 v1.2 — sessions 판정·마킹 컬럼 3종
|
|
-- (신규 DB 는 01-schema.sql 에 반영됨. anchoring 스키마 자체(rate_adjustments·뷰)는
|
|
-- 모듈 소유 DDL schedules/anchoring/schema.sql 로 적용 — 여기엔 두지 않는다.)
|
|
ALTER TABLE negotiation.sessions
|
|
ADD COLUMN IF NOT EXISTS anchor_rate_permille SMALLINT NULL, -- 제안 당시 앵커링 값(천분율) 박제
|
|
ADD COLUMN IF NOT EXISTS last_offered_price BIGINT NULL, -- 협력사 마지막 제시가(가격 흔적)
|
|
ADD COLUMN IF NOT EXISTS anchoring_adjustment_id BIGINT NULL; -- 앵커링 배치 소비 마킹
|