용어 체계: 값=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>
113 lines
4.8 KiB
PL/PgSQL
113 lines
4.8 KiB
PL/PgSQL
-- ============================================================
|
|
-- 앵커링 이름 전면 개편 마이그레이션 (2026-07-06)
|
|
-- rate_adjustments → adjustments (+컬럼 6종)
|
|
-- sessions 앵커링 컬럼 4종, 뷰 2종(rate_history/current_rates → value_history/current_values)
|
|
-- 대상: 구 이름 스키마가 이미 적용된 기존 DB (신규 DB 는 schema.sql 만 적용하면 됨)
|
|
-- 멱등: 각 rename 은 구 이름 존재 시에만 수행 — 재실행·부분 적용 상태에서도 안전
|
|
-- 적용: psql -h <host> -U <user> -d negosium_db -f migrations/20260706_rename_anchoring.sql
|
|
-- ============================================================
|
|
\connect negosium_db
|
|
|
|
BEGIN;
|
|
|
|
-- 1) 구 이름 뷰 제거 (신 이름 뷰는 마지막에 재생성 — 정의는 schema.sql 과 동일)
|
|
DROP VIEW IF EXISTS anchoring.rate_history;
|
|
DROP VIEW IF EXISTS anchoring.current_rates;
|
|
|
|
-- 2) 테이블·시퀀스·인덱스 rename
|
|
DO $$
|
|
BEGIN
|
|
IF EXISTS (SELECT FROM information_schema.tables
|
|
WHERE table_schema = 'anchoring' AND table_name = 'rate_adjustments') THEN
|
|
ALTER TABLE anchoring.rate_adjustments RENAME TO adjustments;
|
|
END IF;
|
|
IF EXISTS (SELECT FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
WHERE n.nspname = 'anchoring' AND c.relname = 'rate_adjustments_id_seq') THEN
|
|
ALTER SEQUENCE anchoring.rate_adjustments_id_seq RENAME TO adjustments_adjustment_id_seq;
|
|
END IF;
|
|
IF EXISTS (SELECT FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace
|
|
WHERE n.nspname = 'anchoring' AND c.relname = 'idx_rate_adjustments_cell') THEN
|
|
ALTER INDEX anchoring.idx_rate_adjustments_cell RENAME TO idx_adjustments_cell;
|
|
END IF;
|
|
-- 테이블 rename 은 PK 제약 이름을 바꾸지 않는다 — 함께 정리
|
|
IF EXISTS (SELECT FROM pg_constraint con JOIN pg_namespace n ON n.oid = con.connamespace
|
|
WHERE n.nspname = 'anchoring' AND con.conname = 'rate_adjustments_pkey') THEN
|
|
ALTER TABLE anchoring.adjustments RENAME CONSTRAINT rate_adjustments_pkey TO adjustments_pkey;
|
|
END IF;
|
|
END $$;
|
|
|
|
-- 3) adjustments 컬럼 rename
|
|
DO $$
|
|
DECLARE
|
|
r RECORD;
|
|
BEGIN
|
|
FOR r IN
|
|
SELECT * FROM (VALUES
|
|
('id', 'adjustment_id'),
|
|
('price_bracket_index', 'price_range_index'),
|
|
('nego_count', 'sample_count'),
|
|
('anchor_rate_before', 'anchoring_value_before'),
|
|
('anchor_rate_after', 'anchoring_value_after'),
|
|
('consumed_session_ids', 'used_session_ids')
|
|
) AS m(old_name, new_name)
|
|
LOOP
|
|
IF EXISTS (SELECT FROM information_schema.columns
|
|
WHERE table_schema = 'anchoring' AND table_name = 'adjustments'
|
|
AND column_name = r.old_name) THEN
|
|
EXECUTE format('ALTER TABLE anchoring.adjustments RENAME COLUMN %I TO %I',
|
|
r.old_name, r.new_name);
|
|
END IF;
|
|
END LOOP;
|
|
END $$;
|
|
|
|
-- 4) negotiation.sessions 앵커링 컬럼 rename
|
|
-- (부분 인덱스 idx_sessions_anchoring_pending 술어는 컬럼 rename 을 자동 추종 — 재생성 불필요)
|
|
DO $$
|
|
DECLARE
|
|
r RECORD;
|
|
BEGIN
|
|
FOR r IN
|
|
SELECT * FROM (VALUES
|
|
('target_anchoring_price', 'anchoring_price'),
|
|
('anchor_rate_permille', 'anchoring_value'),
|
|
('last_offered_price', 'last_offer_price'),
|
|
('anchoring_adjustment_id','used_by_adjustment_id')
|
|
) AS m(old_name, new_name)
|
|
LOOP
|
|
IF EXISTS (SELECT FROM information_schema.columns
|
|
WHERE table_schema = 'negotiation' AND table_name = 'sessions'
|
|
AND column_name = r.old_name) THEN
|
|
EXECUTE format('ALTER TABLE negotiation.sessions RENAME COLUMN %I TO %I',
|
|
r.old_name, r.new_name);
|
|
END IF;
|
|
END LOOP;
|
|
END $$;
|
|
|
|
-- 5) 신 이름 뷰 재생성 (schema.sql §조회용 뷰와 동일 정의)
|
|
CREATE OR REPLACE VIEW anchoring.value_history AS
|
|
SELECT adjustment_id,
|
|
company_id,
|
|
supplier_type,
|
|
price_range_index,
|
|
anchoring_value_before,
|
|
anchoring_value_after,
|
|
anchoring_value_after - anchoring_value_before AS value_change,
|
|
sample_count,
|
|
success_count,
|
|
round(success_count::numeric / sample_count, 3) AS success_rate,
|
|
created_at
|
|
FROM anchoring.adjustments;
|
|
|
|
CREATE OR REPLACE VIEW anchoring.current_values AS
|
|
SELECT DISTINCT ON (company_id, supplier_type, price_range_index)
|
|
company_id,
|
|
supplier_type,
|
|
price_range_index,
|
|
anchoring_value_after AS anchoring_value,
|
|
adjustment_id AS last_adjustment_id,
|
|
created_at AS last_adjusted_at
|
|
FROM anchoring.adjustments
|
|
ORDER BY company_id, supplier_type, price_range_index, adjustment_id DESC;
|
|
|
|
COMMIT;
|