fix: auto-fix code issues (cron)
- 修复重复导入/字段 - 修复异常处理 - 修复PEP8格式问题 - 添加类型注解
This commit is contained in:
@@ -10,25 +10,26 @@ InsightFlow Growth Manager - Phase 8 Task 5
|
||||
作者: InsightFlow Team
|
||||
"""
|
||||
|
||||
import os
|
||||
import json
|
||||
import sqlite3
|
||||
import httpx
|
||||
import asyncio
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import random
|
||||
from typing import List, Dict, Optional, Any, Tuple
|
||||
import re
|
||||
import sqlite3
|
||||
import uuid
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime, timedelta
|
||||
from enum import Enum
|
||||
import hashlib
|
||||
import uuid
|
||||
import re
|
||||
from enum import StrEnum
|
||||
from typing import Any
|
||||
|
||||
import httpx
|
||||
|
||||
# Database path
|
||||
DB_PATH = os.path.join(os.path.dirname(__file__), "insightflow.db")
|
||||
|
||||
|
||||
class EventType(str, Enum):
|
||||
class EventType(StrEnum):
|
||||
"""事件类型"""
|
||||
|
||||
PAGE_VIEW = "page_view" # 页面浏览
|
||||
@@ -44,7 +45,7 @@ class EventType(str, Enum):
|
||||
REFERRAL_REWARD = "referral_reward" # 推荐奖励
|
||||
|
||||
|
||||
class ExperimentStatus(str, Enum):
|
||||
class ExperimentStatus(StrEnum):
|
||||
"""实验状态"""
|
||||
|
||||
DRAFT = "draft" # 草稿
|
||||
@@ -54,7 +55,7 @@ class ExperimentStatus(str, Enum):
|
||||
ARCHIVED = "archived" # 已归档
|
||||
|
||||
|
||||
class TrafficAllocationType(str, Enum):
|
||||
class TrafficAllocationType(StrEnum):
|
||||
"""流量分配类型"""
|
||||
|
||||
RANDOM = "random" # 随机分配
|
||||
@@ -62,7 +63,7 @@ class TrafficAllocationType(str, Enum):
|
||||
TARGETED = "targeted" # 定向分配
|
||||
|
||||
|
||||
class EmailTemplateType(str, Enum):
|
||||
class EmailTemplateType(StrEnum):
|
||||
"""邮件模板类型"""
|
||||
|
||||
WELCOME = "welcome" # 欢迎邮件
|
||||
@@ -74,7 +75,7 @@ class EmailTemplateType(str, Enum):
|
||||
NEWSLETTER = "newsletter" # 新闻通讯
|
||||
|
||||
|
||||
class EmailStatus(str, Enum):
|
||||
class EmailStatus(StrEnum):
|
||||
"""邮件状态"""
|
||||
|
||||
DRAFT = "draft" # 草稿
|
||||
@@ -88,7 +89,7 @@ class EmailStatus(str, Enum):
|
||||
FAILED = "failed" # 失败
|
||||
|
||||
|
||||
class WorkflowTriggerType(str, Enum):
|
||||
class WorkflowTriggerType(StrEnum):
|
||||
"""工作流触发类型"""
|
||||
|
||||
USER_SIGNUP = "user_signup" # 用户注册
|
||||
@@ -100,7 +101,7 @@ class WorkflowTriggerType(str, Enum):
|
||||
CUSTOM_EVENT = "custom_event" # 自定义事件
|
||||
|
||||
|
||||
class ReferralStatus(str, Enum):
|
||||
class ReferralStatus(StrEnum):
|
||||
"""推荐状态"""
|
||||
|
||||
PENDING = "pending" # 待处理
|
||||
@@ -118,14 +119,14 @@ class AnalyticsEvent:
|
||||
user_id: str
|
||||
event_type: EventType
|
||||
event_name: str
|
||||
properties: Dict[str, Any] # 事件属性
|
||||
properties: dict[str, Any] # 事件属性
|
||||
timestamp: datetime
|
||||
session_id: Optional[str]
|
||||
device_info: Dict[str, str] # 设备信息
|
||||
referrer: Optional[str]
|
||||
utm_source: Optional[str]
|
||||
utm_medium: Optional[str]
|
||||
utm_campaign: Optional[str]
|
||||
session_id: str | None
|
||||
device_info: dict[str, str] # 设备信息
|
||||
referrer: str | None
|
||||
utm_source: str | None
|
||||
utm_medium: str | None
|
||||
utm_campaign: str | None
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -139,8 +140,8 @@ class UserProfile:
|
||||
last_seen: datetime
|
||||
total_sessions: int
|
||||
total_events: int
|
||||
feature_usage: Dict[str, int] # 功能使用次数
|
||||
subscription_history: List[Dict]
|
||||
feature_usage: dict[str, int] # 功能使用次数
|
||||
subscription_history: list[dict]
|
||||
ltv: float # 生命周期价值
|
||||
churn_risk_score: float # 流失风险分数
|
||||
engagement_score: float # 参与度分数
|
||||
@@ -156,7 +157,7 @@ class Funnel:
|
||||
tenant_id: str
|
||||
name: str
|
||||
description: str
|
||||
steps: List[Dict] # 漏斗步骤
|
||||
steps: list[dict] # 漏斗步骤
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
|
||||
@@ -169,9 +170,9 @@ class FunnelAnalysis:
|
||||
period_start: datetime
|
||||
period_end: datetime
|
||||
total_users: int
|
||||
step_conversions: List[Dict] # 每步转化数据
|
||||
step_conversions: list[dict] # 每步转化数据
|
||||
overall_conversion: float # 总体转化率
|
||||
drop_off_points: List[Dict] # 流失点
|
||||
drop_off_points: list[dict] # 流失点
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -184,14 +185,14 @@ class Experiment:
|
||||
description: str
|
||||
hypothesis: str
|
||||
status: ExperimentStatus
|
||||
variants: List[Dict] # 实验变体
|
||||
variants: list[dict] # 实验变体
|
||||
traffic_allocation: TrafficAllocationType
|
||||
traffic_split: Dict[str, float] # 流量分配比例
|
||||
target_audience: Dict # 目标受众
|
||||
traffic_split: dict[str, float] # 流量分配比例
|
||||
target_audience: dict # 目标受众
|
||||
primary_metric: str # 主要指标
|
||||
secondary_metrics: List[str] # 次要指标
|
||||
start_date: Optional[datetime]
|
||||
end_date: Optional[datetime]
|
||||
secondary_metrics: list[str] # 次要指标
|
||||
start_date: datetime | None
|
||||
end_date: datetime | None
|
||||
min_sample_size: int # 最小样本量
|
||||
confidence_level: float # 置信水平
|
||||
created_at: datetime
|
||||
@@ -210,7 +211,7 @@ class ExperimentResult:
|
||||
sample_size: int
|
||||
mean_value: float
|
||||
std_dev: float
|
||||
confidence_interval: Tuple[float, float]
|
||||
confidence_interval: tuple[float, float]
|
||||
p_value: float
|
||||
is_significant: bool
|
||||
uplift: float # 提升幅度
|
||||
@@ -228,11 +229,11 @@ class EmailTemplate:
|
||||
subject: str
|
||||
html_content: str
|
||||
text_content: str
|
||||
variables: List[str] # 模板变量
|
||||
preview_text: Optional[str]
|
||||
variables: list[str] # 模板变量
|
||||
preview_text: str | None
|
||||
from_name: str
|
||||
from_email: str
|
||||
reply_to: Optional[str]
|
||||
reply_to: str | None
|
||||
is_active: bool
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
@@ -254,9 +255,9 @@ class EmailCampaign:
|
||||
clicked_count: int
|
||||
bounced_count: int
|
||||
failed_count: int
|
||||
scheduled_at: Optional[datetime]
|
||||
started_at: Optional[datetime]
|
||||
completed_at: Optional[datetime]
|
||||
scheduled_at: datetime | None
|
||||
started_at: datetime | None
|
||||
completed_at: datetime | None
|
||||
created_at: datetime
|
||||
|
||||
|
||||
@@ -272,13 +273,13 @@ class EmailLog:
|
||||
template_id: str
|
||||
status: EmailStatus
|
||||
subject: str
|
||||
sent_at: Optional[datetime]
|
||||
delivered_at: Optional[datetime]
|
||||
opened_at: Optional[datetime]
|
||||
clicked_at: Optional[datetime]
|
||||
ip_address: Optional[str]
|
||||
user_agent: Optional[str]
|
||||
error_message: Optional[str]
|
||||
sent_at: datetime | None
|
||||
delivered_at: datetime | None
|
||||
opened_at: datetime | None
|
||||
clicked_at: datetime | None
|
||||
ip_address: str | None
|
||||
user_agent: str | None
|
||||
error_message: str | None
|
||||
created_at: datetime
|
||||
|
||||
|
||||
@@ -291,8 +292,8 @@ class AutomationWorkflow:
|
||||
name: str
|
||||
description: str
|
||||
trigger_type: WorkflowTriggerType
|
||||
trigger_conditions: Dict # 触发条件
|
||||
actions: List[Dict] # 执行动作
|
||||
trigger_conditions: dict # 触发条件
|
||||
actions: list[dict] # 执行动作
|
||||
is_active: bool
|
||||
execution_count: int
|
||||
created_at: datetime
|
||||
@@ -327,15 +328,15 @@ class Referral:
|
||||
program_id: str
|
||||
tenant_id: str
|
||||
referrer_id: str # 推荐人
|
||||
referee_id: Optional[str] # 被推荐人
|
||||
referee_id: str | None # 被推荐人
|
||||
referral_code: str
|
||||
status: ReferralStatus
|
||||
referrer_rewarded: bool
|
||||
referee_rewarded: bool
|
||||
referrer_reward_value: float
|
||||
referee_reward_value: float
|
||||
converted_at: Optional[datetime]
|
||||
rewarded_at: Optional[datetime]
|
||||
converted_at: datetime | None
|
||||
rewarded_at: datetime | None
|
||||
expires_at: datetime
|
||||
created_at: datetime
|
||||
|
||||
@@ -382,11 +383,11 @@ class GrowthManager:
|
||||
user_id: str,
|
||||
event_type: EventType,
|
||||
event_name: str,
|
||||
properties: Dict = None,
|
||||
properties: dict = None,
|
||||
session_id: str = None,
|
||||
device_info: Dict = None,
|
||||
device_info: dict = None,
|
||||
referrer: str = None,
|
||||
utm_params: Dict = None,
|
||||
utm_params: dict = None,
|
||||
) -> AnalyticsEvent:
|
||||
"""追踪事件"""
|
||||
event_id = f"evt_{uuid.uuid4().hex[:16]}"
|
||||
@@ -554,7 +555,7 @@ class GrowthManager:
|
||||
|
||||
conn.commit()
|
||||
|
||||
def get_user_profile(self, tenant_id: str, user_id: str) -> Optional[UserProfile]:
|
||||
def get_user_profile(self, tenant_id: str, user_id: str) -> UserProfile | None:
|
||||
"""获取用户画像"""
|
||||
with self._get_db() as conn:
|
||||
row = conn.execute(
|
||||
@@ -567,7 +568,7 @@ class GrowthManager:
|
||||
|
||||
def get_user_analytics_summary(
|
||||
self, tenant_id: str, start_date: datetime = None, end_date: datetime = None
|
||||
) -> Dict:
|
||||
) -> dict:
|
||||
"""获取用户分析汇总"""
|
||||
with self._get_db() as conn:
|
||||
query = """
|
||||
@@ -619,7 +620,7 @@ class GrowthManager:
|
||||
"event_type_distribution": {r["event_type"]: r["count"] for r in type_rows},
|
||||
}
|
||||
|
||||
def create_funnel(self, tenant_id: str, name: str, description: str, steps: List[Dict], created_by: str) -> Funnel:
|
||||
def create_funnel(self, tenant_id: str, name: str, description: str, steps: list[dict], created_by: str) -> Funnel:
|
||||
"""创建转化漏斗"""
|
||||
funnel_id = f"fnl_{uuid.uuid4().hex[:16]}"
|
||||
now = datetime.now().isoformat()
|
||||
@@ -657,7 +658,7 @@ class GrowthManager:
|
||||
|
||||
def analyze_funnel(
|
||||
self, funnel_id: str, period_start: datetime = None, period_end: datetime = None
|
||||
) -> Optional[FunnelAnalysis]:
|
||||
) -> FunnelAnalysis | None:
|
||||
"""分析漏斗转化率"""
|
||||
with self._get_db() as conn:
|
||||
funnel_row = conn.execute("SELECT * FROM funnels WHERE id = ?", (funnel_id,)).fetchone()
|
||||
@@ -728,7 +729,7 @@ class GrowthManager:
|
||||
drop_off_points=drop_off_points,
|
||||
)
|
||||
|
||||
def calculate_retention(self, tenant_id: str, cohort_date: datetime, periods: List[int] = None) -> Dict:
|
||||
def calculate_retention(self, tenant_id: str, cohort_date: datetime, periods: list[int] = None) -> dict:
|
||||
"""计算留存率"""
|
||||
if periods is None:
|
||||
periods = [1, 3, 7, 14, 30]
|
||||
@@ -787,12 +788,12 @@ class GrowthManager:
|
||||
name: str,
|
||||
description: str,
|
||||
hypothesis: str,
|
||||
variants: List[Dict],
|
||||
variants: list[dict],
|
||||
traffic_allocation: TrafficAllocationType,
|
||||
traffic_split: Dict[str, float],
|
||||
target_audience: Dict,
|
||||
traffic_split: dict[str, float],
|
||||
target_audience: dict,
|
||||
primary_metric: str,
|
||||
secondary_metrics: List[str],
|
||||
secondary_metrics: list[str],
|
||||
min_sample_size: int = 100,
|
||||
confidence_level: float = 0.95,
|
||||
created_by: str = None,
|
||||
@@ -859,7 +860,7 @@ class GrowthManager:
|
||||
|
||||
return experiment
|
||||
|
||||
def get_experiment(self, experiment_id: str) -> Optional[Experiment]:
|
||||
def get_experiment(self, experiment_id: str) -> Experiment | None:
|
||||
"""获取实验详情"""
|
||||
with self._get_db() as conn:
|
||||
row = conn.execute("SELECT * FROM experiments WHERE id = ?", (experiment_id,)).fetchone()
|
||||
@@ -868,7 +869,7 @@ class GrowthManager:
|
||||
return self._row_to_experiment(row)
|
||||
return None
|
||||
|
||||
def list_experiments(self, tenant_id: str, status: ExperimentStatus = None) -> List[Experiment]:
|
||||
def list_experiments(self, tenant_id: str, status: ExperimentStatus = None) -> list[Experiment]:
|
||||
"""列出实验"""
|
||||
query = "SELECT * FROM experiments WHERE tenant_id = ?"
|
||||
params = [tenant_id]
|
||||
@@ -883,7 +884,7 @@ class GrowthManager:
|
||||
rows = conn.execute(query, params).fetchall()
|
||||
return [self._row_to_experiment(row) for row in rows]
|
||||
|
||||
def assign_variant(self, experiment_id: str, user_id: str, user_attributes: Dict = None) -> Optional[str]:
|
||||
def assign_variant(self, experiment_id: str, user_id: str, user_attributes: dict = None) -> str | None:
|
||||
"""为用户分配实验变体"""
|
||||
experiment = self.get_experiment(experiment_id)
|
||||
if not experiment or experiment.status != ExperimentStatus.RUNNING:
|
||||
@@ -929,7 +930,7 @@ class GrowthManager:
|
||||
|
||||
return variant_id
|
||||
|
||||
def _random_allocation(self, variants: List[Dict], traffic_split: Dict[str, float]) -> str:
|
||||
def _random_allocation(self, variants: list[dict], traffic_split: dict[str, float]) -> str:
|
||||
"""随机分配"""
|
||||
variant_ids = [v["id"] for v in variants]
|
||||
weights = [traffic_split.get(v_id, 1.0 / len(variants)) for v_id in variant_ids]
|
||||
@@ -940,7 +941,7 @@ class GrowthManager:
|
||||
return random.choices(variant_ids, weights=normalized_weights, k=1)[0]
|
||||
|
||||
def _stratified_allocation(
|
||||
self, variants: List[Dict], traffic_split: Dict[str, float], user_attributes: Dict
|
||||
self, variants: list[dict], traffic_split: dict[str, float], user_attributes: dict
|
||||
) -> str:
|
||||
"""分层分配(基于用户属性)"""
|
||||
# 简化的分层分配:根据用户 ID 哈希值分配
|
||||
@@ -952,7 +953,7 @@ class GrowthManager:
|
||||
|
||||
return self._random_allocation(variants, traffic_split)
|
||||
|
||||
def _targeted_allocation(self, variants: List[Dict], target_audience: Dict, user_attributes: Dict) -> Optional[str]:
|
||||
def _targeted_allocation(self, variants: list[dict], target_audience: dict, user_attributes: dict) -> str | None:
|
||||
"""定向分配(基于目标受众条件)"""
|
||||
# 检查用户是否符合目标受众条件
|
||||
conditions = target_audience.get("conditions", [])
|
||||
@@ -1005,7 +1006,7 @@ class GrowthManager:
|
||||
)
|
||||
conn.commit()
|
||||
|
||||
def analyze_experiment(self, experiment_id: str) -> Dict:
|
||||
def analyze_experiment(self, experiment_id: str) -> dict:
|
||||
"""分析实验结果"""
|
||||
experiment = self.get_experiment(experiment_id)
|
||||
if not experiment:
|
||||
@@ -1083,7 +1084,7 @@ class GrowthManager:
|
||||
"variant_results": results,
|
||||
}
|
||||
|
||||
def start_experiment(self, experiment_id: str) -> Optional[Experiment]:
|
||||
def start_experiment(self, experiment_id: str) -> Experiment | None:
|
||||
"""启动实验"""
|
||||
with self._get_db() as conn:
|
||||
now = datetime.now().isoformat()
|
||||
@@ -1099,7 +1100,7 @@ class GrowthManager:
|
||||
|
||||
return self.get_experiment(experiment_id)
|
||||
|
||||
def stop_experiment(self, experiment_id: str) -> Optional[Experiment]:
|
||||
def stop_experiment(self, experiment_id: str) -> Experiment | None:
|
||||
"""停止实验"""
|
||||
with self._get_db() as conn:
|
||||
now = datetime.now().isoformat()
|
||||
@@ -1125,7 +1126,7 @@ class GrowthManager:
|
||||
subject: str,
|
||||
html_content: str,
|
||||
text_content: str = None,
|
||||
variables: List[str] = None,
|
||||
variables: list[str] = None,
|
||||
from_name: str = None,
|
||||
from_email: str = None,
|
||||
reply_to: str = None,
|
||||
@@ -1185,7 +1186,7 @@ class GrowthManager:
|
||||
|
||||
return template
|
||||
|
||||
def get_email_template(self, template_id: str) -> Optional[EmailTemplate]:
|
||||
def get_email_template(self, template_id: str) -> EmailTemplate | None:
|
||||
"""获取邮件模板"""
|
||||
with self._get_db() as conn:
|
||||
row = conn.execute("SELECT * FROM email_templates WHERE id = ?", (template_id,)).fetchone()
|
||||
@@ -1194,7 +1195,7 @@ class GrowthManager:
|
||||
return self._row_to_email_template(row)
|
||||
return None
|
||||
|
||||
def list_email_templates(self, tenant_id: str, template_type: EmailTemplateType = None) -> List[EmailTemplate]:
|
||||
def list_email_templates(self, tenant_id: str, template_type: EmailTemplateType = None) -> list[EmailTemplate]:
|
||||
"""列出邮件模板"""
|
||||
query = "SELECT * FROM email_templates WHERE tenant_id = ? AND is_active = 1"
|
||||
params = [tenant_id]
|
||||
@@ -1209,7 +1210,7 @@ class GrowthManager:
|
||||
rows = conn.execute(query, params).fetchall()
|
||||
return [self._row_to_email_template(row) for row in rows]
|
||||
|
||||
def render_template(self, template_id: str, variables: Dict) -> Dict[str, str]:
|
||||
def render_template(self, template_id: str, variables: dict) -> dict[str, str]:
|
||||
"""渲染邮件模板"""
|
||||
template = self.get_email_template(template_id)
|
||||
if not template:
|
||||
@@ -1235,7 +1236,7 @@ class GrowthManager:
|
||||
}
|
||||
|
||||
def create_email_campaign(
|
||||
self, tenant_id: str, name: str, template_id: str, recipient_list: List[Dict], scheduled_at: datetime = None
|
||||
self, tenant_id: str, name: str, template_id: str, recipient_list: list[dict], scheduled_at: datetime = None
|
||||
) -> EmailCampaign:
|
||||
"""创建邮件营销活动"""
|
||||
campaign_id = f"ec_{uuid.uuid4().hex[:16]}"
|
||||
@@ -1314,7 +1315,7 @@ class GrowthManager:
|
||||
|
||||
return campaign
|
||||
|
||||
async def send_email(self, campaign_id: str, user_id: str, email: str, template_id: str, variables: Dict) -> bool:
|
||||
async def send_email(self, campaign_id: str, user_id: str, email: str, template_id: str, variables: dict) -> bool:
|
||||
"""发送单封邮件"""
|
||||
template = self.get_email_template(template_id)
|
||||
if not template:
|
||||
@@ -1380,7 +1381,7 @@ class GrowthManager:
|
||||
conn.commit()
|
||||
return False
|
||||
|
||||
async def send_campaign(self, campaign_id: str) -> Dict:
|
||||
async def send_campaign(self, campaign_id: str) -> dict:
|
||||
"""发送整个营销活动"""
|
||||
with self._get_db() as conn:
|
||||
campaign_row = conn.execute("SELECT * FROM email_campaigns WHERE id = ?", (campaign_id,)).fetchone()
|
||||
@@ -1432,7 +1433,7 @@ class GrowthManager:
|
||||
|
||||
return {"campaign_id": campaign_id, "total": len(logs), "success": success_count, "failed": failed_count}
|
||||
|
||||
def _get_user_variables(self, tenant_id: str, user_id: str) -> Dict:
|
||||
def _get_user_variables(self, tenant_id: str, user_id: str) -> dict:
|
||||
"""获取用户变量用于邮件模板"""
|
||||
# 这里应该从用户服务获取用户信息
|
||||
# 简化实现
|
||||
@@ -1444,8 +1445,8 @@ class GrowthManager:
|
||||
name: str,
|
||||
description: str,
|
||||
trigger_type: WorkflowTriggerType,
|
||||
trigger_conditions: Dict,
|
||||
actions: List[Dict],
|
||||
trigger_conditions: dict,
|
||||
actions: list[dict],
|
||||
) -> AutomationWorkflow:
|
||||
"""创建自动化工作流"""
|
||||
workflow_id = f"aw_{uuid.uuid4().hex[:16]}"
|
||||
@@ -1491,7 +1492,7 @@ class GrowthManager:
|
||||
|
||||
return workflow
|
||||
|
||||
async def trigger_workflow(self, workflow_id: str, event_data: Dict):
|
||||
async def trigger_workflow(self, workflow_id: str, event_data: dict):
|
||||
"""触发自动化工作流"""
|
||||
with self._get_db() as conn:
|
||||
row = conn.execute(
|
||||
@@ -1519,7 +1520,7 @@ class GrowthManager:
|
||||
|
||||
return True
|
||||
|
||||
def _check_trigger_conditions(self, conditions: Dict, event_data: Dict) -> bool:
|
||||
def _check_trigger_conditions(self, conditions: dict, event_data: dict) -> bool:
|
||||
"""检查触发条件"""
|
||||
# 简化的条件检查
|
||||
for key, value in conditions.items():
|
||||
@@ -1527,7 +1528,7 @@ class GrowthManager:
|
||||
return False
|
||||
return True
|
||||
|
||||
async def _execute_action(self, action: Dict, event_data: Dict):
|
||||
async def _execute_action(self, action: dict, event_data: dict):
|
||||
"""执行工作流动作"""
|
||||
action_type = action.get("type")
|
||||
|
||||
@@ -1691,7 +1692,7 @@ class GrowthManager:
|
||||
if not row:
|
||||
return code
|
||||
|
||||
def _get_referral_program(self, program_id: str) -> Optional[ReferralProgram]:
|
||||
def _get_referral_program(self, program_id: str) -> ReferralProgram | None:
|
||||
"""获取推荐计划"""
|
||||
with self._get_db() as conn:
|
||||
row = conn.execute("SELECT * FROM referral_programs WHERE id = ?", (program_id,)).fetchone()
|
||||
@@ -1746,7 +1747,7 @@ class GrowthManager:
|
||||
|
||||
return True
|
||||
|
||||
def get_referral_stats(self, program_id: str) -> Dict:
|
||||
def get_referral_stats(self, program_id: str) -> dict:
|
||||
"""获取推荐统计"""
|
||||
with self._get_db() as conn:
|
||||
stats = conn.execute(
|
||||
@@ -1841,7 +1842,7 @@ class GrowthManager:
|
||||
|
||||
def check_team_incentive_eligibility(
|
||||
self, tenant_id: str, current_tier: str, team_size: int
|
||||
) -> List[TeamIncentive]:
|
||||
) -> list[TeamIncentive]:
|
||||
"""检查团队激励资格"""
|
||||
with self._get_db() as conn:
|
||||
now = datetime.now().isoformat()
|
||||
@@ -1859,7 +1860,7 @@ class GrowthManager:
|
||||
|
||||
# ==================== 实时分析仪表板 ====================
|
||||
|
||||
def get_realtime_dashboard(self, tenant_id: str) -> Dict:
|
||||
def get_realtime_dashboard(self, tenant_id: str) -> dict:
|
||||
"""获取实时分析仪表板数据"""
|
||||
now = datetime.now()
|
||||
today_start = now.replace(hour=0, minute=0, second=0, microsecond=0)
|
||||
|
||||
Reference in New Issue
Block a user