Files
Neo-ZQYY/apps/backend/app/schemas/xcx_board.py

434 lines
11 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.
"""三看板接口 Pydantic SchemaBOARD-1/2/3 请求参数枚举 + 响应模型)。"""
from __future__ import annotations
from enum import Enum
from app.schemas.base import CamelModel
# ---------------------------------------------------------------------------
# 请求参数枚举Task 2.1
# ---------------------------------------------------------------------------
class CoachSortEnum(str, Enum):
"""BOARD-1 排序维度。"""
perf_desc = "perf_desc"
perf_asc = "perf_asc"
salary_desc = "salary_desc"
salary_asc = "salary_asc"
sv_desc = "sv_desc"
task_desc = "task_desc"
class SkillFilterEnum(str, Enum):
"""BOARD-1 技能筛选。"""
all = "all"
chinese = "chinese"
snooker = "snooker"
mahjong = "mahjong"
karaoke = "karaoke"
class BoardTimeEnum(str, Enum):
"""BOARD-1 时间范围。"""
month = "month"
quarter = "quarter"
last_month = "last_month"
last_3m = "last_3m"
last_quarter = "last_quarter"
last_6m = "last_6m"
class CustomerDimensionEnum(str, Enum):
"""BOARD-2 客户维度。"""
recall = "recall"
potential = "potential"
balance = "balance"
recharge = "recharge"
recent = "recent"
spend60 = "spend60"
freq60 = "freq60"
loyal = "loyal"
class ProjectFilterEnum(str, Enum):
"""BOARD-2 项目筛选。"""
all = "all"
chinese = "chinese"
snooker = "snooker"
mahjong = "mahjong"
karaoke = "karaoke"
class FinanceTimeEnum(str, Enum):
"""BOARD-3 时间范围。"""
month = "month"
lastMonth = "lastMonth"
week = "week"
lastWeek = "lastWeek"
quarter3 = "quarter3"
quarter = "quarter"
lastQuarter = "lastQuarter"
half6 = "half6"
class AreaFilterEnum(str, Enum):
"""BOARD-3 区域筛选。"""
all = "all"
hall = "hall"
hallA = "hallA"
hallB = "hallB"
hallC = "hallC"
mahjong = "mahjong"
teamBuilding = "teamBuilding"
# ---------------------------------------------------------------------------
# BOARD-1 响应 SchemaTask 2.2
# ---------------------------------------------------------------------------
class CoachSkillItem(CamelModel):
text: str
cls: str
class CoachBoardItem(CamelModel):
"""助教看板单条记录(扁平结构,包含所有维度字段)。"""
# 基础字段(所有维度共享)
id: int
name: str
initial: str
avatar_gradient: str
level: str # star/senior/middle/junior
skills: list[CoachSkillItem]
top_customers: list[str] # ["💖 王先生", "💛 李女士"]
# perf 维度
perf_hours: float = 0.0
perf_hours_before: float | None = None
perf_gap: str | None = None # "距升档 13.8h" 或 None
perf_reached: bool = False
# salary 维度
salary: float = 0.0
salary_perf_hours: float = 0.0
salary_perf_before: float | None = None
# sv 维度
sv_amount: float = 0.0
sv_customer_count: int = 0
sv_consume: float = 0.0
# task 维度
task_recall: int = 0
task_callback: int = 0
class CoachBoardResponse(CamelModel):
items: list[CoachBoardItem]
dim_type: str # perf/salary/sv/task
# ---------------------------------------------------------------------------
# BOARD-2 响应 SchemaTask 2.3
# ---------------------------------------------------------------------------
class CustomerAssistant(CamelModel):
name: str
cls: str
heart_score: float
badge: str | None = None
badge_cls: str | None = None
class CustomerBoardItemBase(CamelModel):
"""客户看板基础字段(所有维度共享)。"""
id: int
name: str
initial: str
avatar_cls: str
assistants: list[CustomerAssistant]
class RecallItem(CustomerBoardItemBase):
ideal_days: int
elapsed_days: int
overdue_days: int
visits_30d: int
balance: str
recall_index: float
class PotentialTag(CamelModel):
text: str
theme: str
class PotentialItem(CustomerBoardItemBase):
potential_tags: list[PotentialTag]
spend_30d: float
avg_visits: float
avg_spend: float
class BalanceItem(CustomerBoardItemBase):
balance: str
last_visit: str # "3天前"
monthly_consume: float
available_months: str # "约0.8个月"
class RechargeItem(CustomerBoardItemBase):
last_recharge: str
recharge_amount: float
recharges_60d: int
current_balance: str
class RecentItem(CustomerBoardItemBase):
days_ago: int
visit_freq: str # "6.2次/月"
ideal_days: int
visits_30d: int
avg_spend: float
class Spend60Item(CustomerBoardItemBase):
spend_60d: float
visits_60d: int
high_spend_tag: bool
avg_spend: float
class WeeklyVisit(CamelModel):
val: int
pct: int # 0-100
class Freq60Item(CustomerBoardItemBase):
visits_60d: int
avg_interval: str # "5.0天"
weekly_visits: list[WeeklyVisit] # 固定长度 8
spend_60d: float
class CoachDetail(CamelModel):
name: str
cls: str
heart_score: float
badge: str | None = None
avg_duration: str
service_count: int
coach_spend: float
relation_idx: float
class LoyalItem(CustomerBoardItemBase):
intimacy: float
top_coach_name: str
top_coach_heart: float
top_coach_score: float
coach_name: str
coach_ratio: str # "78%"
coach_details: list[CoachDetail]
class CustomerBoardResponse(CamelModel):
items: list[dict] # 实际类型取决于 dimension
total: int
page: int
page_size: int
# ---------------------------------------------------------------------------
# BOARD-3 响应 SchemaTask 2.4
# ---------------------------------------------------------------------------
class OverviewPanel(CamelModel):
"""经营一览8 项核心指标 + 各 3 个环比字段Optionalcompare=0 时为 None"""
occurrence: float
discount: float # 负值
discount_rate: float
confirmed_revenue: float
cash_in: float
cash_out: float
cash_balance: float
balance_rate: float
# occurrence 环比
occurrence_compare: str | None = None
occurrence_down: bool | None = None
occurrence_flat: bool | None = None
# discount 环比
discount_compare: str | None = None
discount_down: bool | None = None
discount_flat: bool | None = None
# discount_rate 环比
discount_rate_compare: str | None = None
discount_rate_down: bool | None = None
discount_rate_flat: bool | None = None
# confirmed_revenue 环比
confirmed_revenue_compare: str | None = None
confirmed_revenue_down: bool | None = None
confirmed_revenue_flat: bool | None = None
# cash_in 环比
cash_in_compare: str | None = None
cash_in_down: bool | None = None
cash_in_flat: bool | None = None
# cash_out 环比
cash_out_compare: str | None = None
cash_out_down: bool | None = None
cash_out_flat: bool | None = None
# cash_balance 环比
cash_balance_compare: str | None = None
cash_balance_down: bool | None = None
cash_balance_flat: bool | None = None
# balance_rate 环比
balance_rate_compare: str | None = None
balance_rate_down: bool | None = None
balance_rate_flat: bool | None = None
class GiftCell(CamelModel):
value: float
compare: str | None = None
down: bool | None = None
flat: bool | None = None
class GiftRow(CamelModel):
"""赠送卡矩阵一行:合计 / 酒水卡 / 台费卡 / 抵用券。"""
label: str # "新增" / "消费" / "余额"
total: GiftCell
liquor: GiftCell
table_fee: GiftCell
voucher: GiftCell
class RechargePanel(CamelModel):
"""预收资产板块:储值卡 5 指标 + 赠送卡 3×4 矩阵 + 全卡余额。"""
actual_income: float
first_charge: float
renew_charge: float
consumed: float
card_balance: float
gift_rows: list[GiftRow] # 3 行
all_card_balance: float
# 储值卡各项环比字段
actual_income_compare: str | None = None
actual_income_down: bool | None = None
actual_income_flat: bool | None = None
first_charge_compare: str | None = None
first_charge_down: bool | None = None
first_charge_flat: bool | None = None
renew_charge_compare: str | None = None
renew_charge_down: bool | None = None
renew_charge_flat: bool | None = None
consumed_compare: str | None = None
consumed_down: bool | None = None
consumed_flat: bool | None = None
card_balance_compare: str | None = None
card_balance_down: bool | None = None
card_balance_flat: bool | None = None
class RevenueStructureRow(CamelModel):
id: str
name: str
desc: str | None = None
is_sub: bool = False
amount: float
discount: float
booked: float
booked_compare: str | None = None
class RevenueItem(CamelModel):
label: str
amount: float
class ChannelItem(CamelModel):
label: str
amount: float
class RevenuePanel(CamelModel):
structure_rows: list[RevenueStructureRow]
price_items: list[RevenueItem] # 4 项
total_occurrence: float
discount_items: list[RevenueItem] # 4 项
confirmed_total: float
channel_items: list[ChannelItem] # 3 项
class CashflowItem(CamelModel):
label: str
amount: float
class CashflowPanel(CamelModel):
consume_items: list[CashflowItem] # 3 项
recharge_items: list[CashflowItem] # 1 项
total: float
class ExpenseItem(CamelModel):
label: str
amount: float
compare: str | None = None
down: bool | None = None
flat: bool | None = None
class ExpensePanel(CamelModel):
operation_items: list[ExpenseItem] # 3 项
fixed_items: list[ExpenseItem] # 4 项
coach_items: list[ExpenseItem] # 4 项
platform_items: list[ExpenseItem] # 3 项
total: float
total_compare: str | None = None
total_down: bool | None = None
total_flat: bool | None = None
class CoachAnalysisRow(CamelModel):
level: str
pay: float
share: float
hourly: float
pay_compare: str | None = None
pay_down: bool | None = None
share_compare: str | None = None
share_down: bool | None = None
hourly_compare: str | None = None
hourly_flat: bool | None = None
class CoachAnalysisTable(CamelModel):
total_pay: float
total_share: float
avg_hourly: float
total_pay_compare: str | None = None
total_pay_down: bool | None = None
total_share_compare: str | None = None
total_share_down: bool | None = None
avg_hourly_compare: str | None = None
avg_hourly_flat: bool | None = None
rows: list[CoachAnalysisRow] # 4 行:初级/中级/高级/星级
class CoachAnalysisPanel(CamelModel):
basic: CoachAnalysisTable # 基础课/陪打
incentive: CoachAnalysisTable # 激励课/超休
class FinanceBoardResponse(CamelModel):
overview: OverviewPanel
recharge: RechargePanel | None # area≠all 时为 null
revenue: RevenuePanel
cashflow: CashflowPanel
expense: ExpensePanel
coach_analysis: CoachAnalysisPanel