58 lines
2.9 KiB
Python
58 lines
2.9 KiB
Python
"""현재 앵커링 값 조회(읽기 경로) — negodata 이식판.
|
|
|
|
원본 reader(schedules/anchoring)는 Redis 캐시를 먼저 보지만, 이식판은 DB 직조회 한 문장만 쓴다
|
|
(2026-07-03 단순화 결정 — 조회가 견적 생성 시에만 일어나 캐시가 불필요, Redis 의존 제거).
|
|
칸별 최신 조정 rate 는 모듈 소유 뷰 `anchoring.current_values` 가 제공하고,
|
|
조정 이력이 없는 칸은 결과에 없으므로 호출측이 정적 테이블 시작값으로 폴백한다.
|
|
|
|
견적 생성이 앵커 조회 때문에 실패해서는 안 된다(인수인계.md §1 규칙 6) — anchoring 스키마
|
|
미적용 환경을 포함해 어떤 실패도 밖으로 던지지 않고 빈 결과(전량 정적 폴백) + WARN 으로 처리한다.
|
|
"""
|
|
from sqlalchemy import column, select, table
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from common.anchoring.constants import ANCHORING_VALUE_MAX, ANCHORING_VALUE_MIN, SAMPLEABLE_SUPPLIER_TYPES
|
|
from common.logger import LOG
|
|
|
|
# 모듈 소유 DDL(postgres-init/05-anchoring-schema.sql)의 조회용 뷰 — negodata 는 ORM 모델 없이 읽기만 한다.
|
|
_current_values = table(
|
|
"current_values",
|
|
column("company_id"),
|
|
column("price_range_index"),
|
|
column("anchoring_value"),
|
|
column("supplier_type"),
|
|
schema="anchoring",
|
|
)
|
|
|
|
|
|
async def fetch_current_values(db: AsyncSession, company_ids: list, supplier_types: list[int]) -> dict:
|
|
"""칸별 현재 앵커링 값 일괄 조회. {(company_id, supplier_type, price_range_index): rate‰} 반환.
|
|
|
|
supplier_type 은 세션의 (item_id, supplier_id) 매핑에서 온 supply_type 이다.
|
|
조정 이력이 없는 칸은 결과에 없다(호출측 정적 폴백). 조회 실패 시 빈 dict."""
|
|
valid_types = sorted({int(t) for t in supplier_types if t in SAMPLEABLE_SUPPLIER_TYPES})
|
|
if not company_ids or not valid_types:
|
|
return {}
|
|
try:
|
|
stmt = select(
|
|
_current_values.c.company_id,
|
|
_current_values.c.supplier_type,
|
|
_current_values.c.price_range_index,
|
|
_current_values.c.anchoring_value,
|
|
).where(
|
|
_current_values.c.company_id.in_(company_ids),
|
|
_current_values.c.supplier_type.in_(valid_types),
|
|
)
|
|
rows = (await db.execute(stmt)).all()
|
|
except Exception as ex:
|
|
LOG.w(f"[앵커링] current_values 조회 실패 — 전량 정적 테이블 폴백: {ex}")
|
|
return {}
|
|
|
|
out = {}
|
|
for company_id, supplier_type, price_range_index, rate in rows:
|
|
if not ANCHORING_VALUE_MIN <= rate <= ANCHORING_VALUE_MAX: # 범위 밖 값은 오염 방어 — 버리고 정적 폴백
|
|
LOG.w(f"[앵커링] rate 범위 밖 — 무시(정적 폴백): company={company_id} type={supplier_type} bracket={price_range_index} rate={rate}")
|
|
continue
|
|
out[(company_id, supplier_type, price_range_index)] = rate
|
|
return out
|