feat(abonnements): paliers LLM Essentielle/Premium, admin modeles par forfait, statistiques revenus, emails marketing
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m51s
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 2m51s
- Gamme officielle : Essentielle (Pro) = deepseek-v4-flash, glm-5.3-flash, minimax-m3 ; Premium (Business) = claude-sonnet-5, deepseek-v4-pro, glm-5.3 - Routage reel : le modele employe suit le palier IA du forfait (reglages admin > defaut du plan), garde anti-croisement de palier - Nouvelle page admin « Modeles & abonnements » (matrice forfaits/paliers, modele par defaut, catalogue OpenRouter) - Statistiques enrichies : revenus (30 j + total), MRR estime, credits, liste d'attente, paliers utilises - Nouvelle page admin « Marketing » : audiences avec compteurs, apercu, envoi test obligatoire, historique, desabonnement public + en-tetes List-Unsubscribe ; .gitignore pour les donnees d'execution - Interface (accueil + tarifs) alignee sur la gamme, 13 langues completes - Tests : routage par palier (fonction + tache), marketing, revenus en base
This commit is contained in:
@@ -51,9 +51,13 @@ async def get_available_providers(
|
||||
"""
|
||||
from routes.admin_routes import load_settings
|
||||
from models.subscription import PlanType, PLANS
|
||||
from routes.translate_routes import _resolve_tier_model
|
||||
|
||||
settings = load_settings()
|
||||
is_dev = os.getenv("APP_ENV", "production").lower() == "development"
|
||||
# Le modèle affiché est celui réellement routé pour le plan de l'appelant
|
||||
# (réglages admin « ai_tiers » > défaut du plan — gamme officielle).
|
||||
user_plan = str(current_user.plan) if current_user is not None else None
|
||||
|
||||
def _key_ready(key_var: str) -> bool:
|
||||
return bool(os.getenv(key_var, "").strip())
|
||||
@@ -84,12 +88,7 @@ async def get_available_providers(
|
||||
|
||||
# AI Essentielle (OpenRouter — cheap model / Eco)
|
||||
if _is_enabled("openrouter", key_var="OPENROUTER_API_KEY"):
|
||||
or_cfg = getattr(settings, "openrouter", None)
|
||||
model = _resolve_model(
|
||||
or_cfg.model if or_cfg else None,
|
||||
"OPENROUTER_MODEL",
|
||||
"google/gemini-3.5-flash",
|
||||
)
|
||||
model = _resolve_tier_model(settings, user_plan, premium=False)
|
||||
available.append({
|
||||
"id": "openrouter",
|
||||
"label": "Traduction IA Éco",
|
||||
@@ -118,12 +117,7 @@ async def get_available_providers(
|
||||
|
||||
# AI Premium (OpenRouter — premium model)
|
||||
if _is_enabled("openrouter_premium", key_var="OPENROUTER_API_KEY") or _is_enabled("openrouter", key_var="OPENROUTER_API_KEY"):
|
||||
orp_cfg = getattr(settings, "openrouter_premium", None)
|
||||
model = _resolve_model(
|
||||
orp_cfg.model if orp_cfg else None,
|
||||
"OPENROUTER_PREMIUM_MODEL",
|
||||
"anthropic/claude-sonnet-4.6",
|
||||
)
|
||||
model = _resolve_tier_model(settings, user_plan, premium=True)
|
||||
available.append({
|
||||
"id": "openrouter_premium",
|
||||
"label": "Traduction IA Premium",
|
||||
|
||||
Reference in New Issue
Block a user