o2o-negosium-original/negodata/backend/router/v1/statistics/protocol.py

80 lines
2.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from pydantic import Field
from common.models.gmodel import Res_WebPacketProtocol, WebPacketProtocol
class StatisticsProtocol(WebPacketProtocol):
pass
class StatKpi(WebPacketProtocol):
total_savings: int = 0 # 총 절감액(목표가 대비, 낙찰세션 target−bid 합)
savings_rate: float = 0.0 # 평균 절감률 = 절감합/목표합
award_rate: float = 0.0 # 낙찰률 = 낙찰 마감 / 전체 마감
anchor_reach_rate: float = 0.0 # 평균 앵커 도달률 = (목표−투찰)/(목표−앵커)
savings_delta_mom: int = 0 # 전월 대비 절감액 증감
closed_count: int = 0 # 마감 견적 수(창)
regen_avg_round: float = 0.0 # 평균 재견적 라운드
markup_suppression_rate: float = 0.0 # 인상억제율(재협상: 직전 라운드 투찰가 대비 이번 투찰가 인하율, 파생)
class StatMonthPoint(WebPacketProtocol):
month: str # 'YYYY-MM'
savings: int = 0
rate: float = 0.0 # 절감률
class StatMarkupPoint(WebPacketProtocol):
month: str # 'YYYY-MM'
rate: float = 0.0 # 인상억제율(직전 라운드 투찰가 대비 인하율)
class StatOutcome(WebPacketProtocol):
awarded: int = 0 # CloseReason 1
open_price: int = 0 # 5 가격 미달
open_equal: int = 0 # 6 동가
open_noshow: int = 0 # 7 미응찰
open_reject: int = 0 # 8 거부
class StatParticipation(WebPacketProtocol):
bid: int = 0 # 응찰(SessionStatus DONE)
no_participate: int = 0 # 미응찰(NOT_PARTICIPATED)
rejected: int = 0 # 거부(REJECTED)
class StatTypeRow(WebPacketProtocol):
label: str
award_rate: float = 0.0
avg_savings: int = 0
count: int = 0
class StatCategory(WebPacketProtocol):
category: str
savings: int = 0
count: int = 0
class StatCardUsage(WebPacketProtocol):
type: str # 'nego' | 'wild'
label: str
uses: int = 0
avg_drop: int = 0 # 사용 직후 상대 제시가 평균 하락. TODO: v1은 0(유형별 빈도만) — chats seq 델타 계산은 다음 단계.
class StatScope(WebPacketProtocol):
kpi: StatKpi = Field(default_factory=StatKpi)
trend: list[StatMonthPoint] = []
markup_trend: list[StatMarkupPoint] = [] # 월별 인상억제율(재협상)
outcome: StatOutcome = Field(default_factory=StatOutcome)
participation: StatParticipation = Field(default_factory=StatParticipation)
type_split: list[StatTypeRow] = []
categories: list[StatCategory] = []
cards: list[StatCardUsage] = []
class Res_StatisticsSummary(Res_WebPacketProtocol):
company: StatScope = Field(default_factory=StatScope) # 회사 전체(company_id 스코프)
mine: StatScope = Field(default_factory=StatScope) # 내가 만든 견적(user_id 추가 스코프)