- 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>
22 lines
1.1 KiB
Python
22 lines
1.1 KiB
Python
"""순수 계산 함수 — DB 접근 없음. 원본: schedules/anchoring/src/anchoring/service.py 에서
|
||
읽기 경로(칸 해석·앵커가 산출) 두 함수만 발췌 이식. 표본 판정·평가 함수는 배치 전용이라 제외.
|
||
|
||
모든 산술은 정수(천분율 ‰). float 금지 — 1원 단위 내림의 정확성 보장.
|
||
"""
|
||
from bisect import bisect_right
|
||
|
||
from common.anchoring.constants import BRACKET_INDEX_MAX, UPPER_BOUNDS
|
||
|
||
|
||
def calc_bracket_index(target_price: int) -> int:
|
||
"""목표가 → 가격구간 인덱스(0-기반). 자릿수 계단식 사다리.
|
||
|
||
좌폐우개 [이전 ub, ub): 가격이 upper_bound 와 정확히 같으면 다음 칸.
|
||
1억 이상은 마지막 인덱스로 클램프. 정적 테이블 idx = 반환값 + 1"""
|
||
return min(bisect_right(UPPER_BOUNDS, target_price), BRACKET_INDEX_MAX)
|
||
|
||
|
||
def calc_anchor_price(target_price: int, rate_permille: int) -> int:
|
||
"""앵커링가 = 목표가 × (1 − A), 1원 단위 내림. (정수 연산만 — float 곱셈 재도입 금지)"""
|
||
return target_price * (1000 - rate_permille) // 1000
|