system-prompts-and-models-o.../dealix/auto_client_acquisition/revenue_science/expansion_model.py
2026-05-01 14:03:52 +03:00

106 lines
3.3 KiB
Python

"""
Expansion prediction — flags customers ready for upsell / cross-sell.
Drivers (positive signals):
- High health score (>= 75)
- High engagement growth
- Hitting plan limits (e.g., quota of leads/month)
- Multiple sectors targeted
- Strong pipeline added
- Good NPS
Output: ExpansionSignal with recommended package + estimated upsell SAR.
"""
from __future__ import annotations
from dataclasses import dataclass, field
@dataclass
class ExpansionSignal:
customer_id: str
likelihood: float # 0..1
recommended_plan: str # Growth / Scale / Enterprise
estimated_upsell_sar: float # additional MRR
drivers: list[str] = field(default_factory=list)
pitch_angle_ar: str = ""
def predict_expansion(
*,
customer_id: str,
current_plan: str = "Growth",
health_score: float = 0,
monthly_engagement_growth_pct: float = 0,
sectors_targeted: int = 1,
pct_of_quota_used: float = 0, # 0..1 (close to 1 means hitting limits)
nps: int | None = None,
pipeline_added_growth_pct: float = 0,
) -> ExpansionSignal:
"""Score expansion likelihood + recommend the next plan."""
score = 0.0
drivers: list[str] = []
if health_score >= 80:
score += 0.30
drivers.append("Health score ممتاز")
elif health_score >= 65:
score += 0.15
if monthly_engagement_growth_pct >= 0.30:
score += 0.20
drivers.append(f"نمو استخدام {monthly_engagement_growth_pct*100:.0f}%")
if pct_of_quota_used >= 0.85:
score += 0.25
drivers.append("يقترب من حد الباقة")
elif pct_of_quota_used >= 0.70:
score += 0.12
if sectors_targeted >= 3:
score += 0.10
drivers.append("يستهدف قطاعات متعددة")
if nps is not None and nps >= 9:
score += 0.10
drivers.append(f"NPS {nps} (promoter)")
if pipeline_added_growth_pct >= 0.30:
score += 0.15
drivers.append("Pipeline ينمو شهرياً")
score = min(1.0, score)
# Plan ladder
plans_order = ["Starter", "Growth", "Scale", "Enterprise"]
plan_prices = {"Starter": 999, "Growth": 2999, "Scale": 7999, "Enterprise": 15000}
try:
idx = plans_order.index(current_plan)
next_plan = plans_order[min(idx + 1, len(plans_order) - 1)]
except ValueError:
next_plan = "Growth"
upsell_sar = max(0, plan_prices.get(next_plan, 0) - plan_prices.get(current_plan, 0))
if score >= 0.65:
pitch = (
f"العميل ينمو + يقترب من حد الباقة الحالية. ترقية إلى {next_plan} "
f"تفتح: integrations إضافية، multi-sector، QBR شهري. "
f"upsell {upsell_sar:,.0f} ريال/شهر."
)
elif score >= 0.40:
pitch = (
"ركّز على إثبات ROI أولاً عبر Proof Pack — ثم اقترح الترقية في QBR القادم."
)
else:
pitch = "ليس الوقت المناسب — ركّز على retention قبل expansion."
return ExpansionSignal(
customer_id=customer_id,
likelihood=round(score, 3),
recommended_plan=next_plan if score >= 0.5 else current_plan,
estimated_upsell_sar=upsell_sar if score >= 0.5 else 0,
drivers=drivers,
pitch_angle_ar=pitch,
)