80 lines
2.8 KiB
Python
80 lines
2.8 KiB
Python
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 추가 스코프)
|