Update promo.py
This commit is contained in:
@@ -15,6 +15,8 @@ from app.database.crud.discount_offer import (
|
||||
mark_offer_claimed,
|
||||
)
|
||||
from app.database.crud.promo_offer_template import get_promo_offer_template_by_id
|
||||
from app.database.crud.promo_group import get_auto_assign_promo_groups
|
||||
from app.database.crud.transaction import get_user_total_spent_kopeks
|
||||
from app.services.promo_offer_service import promo_offer_service
|
||||
from app.config import settings
|
||||
|
||||
@@ -70,6 +72,29 @@ class PromoGroupDiscounts(BaseModel):
|
||||
period_discounts: Dict[str, int] = {}
|
||||
|
||||
|
||||
class LoyaltyTierInfo(BaseModel):
|
||||
"""Info about a single loyalty tier (promo group)."""
|
||||
id: int
|
||||
name: str
|
||||
threshold_rubles: float
|
||||
server_discount_percent: int = 0
|
||||
traffic_discount_percent: int = 0
|
||||
device_discount_percent: int = 0
|
||||
period_discounts: Dict[str, int] = {}
|
||||
is_current: bool = False
|
||||
is_achieved: bool = False
|
||||
|
||||
|
||||
class LoyaltyTiersResponse(BaseModel):
|
||||
"""Response with all loyalty tiers and user progress."""
|
||||
tiers: List[LoyaltyTierInfo]
|
||||
current_spent_rubles: float
|
||||
current_tier_name: Optional[str] = None
|
||||
next_tier_name: Optional[str] = None
|
||||
next_tier_threshold_rubles: Optional[float] = None
|
||||
progress_percent: float = 0
|
||||
|
||||
|
||||
# ============ Routes ============
|
||||
|
||||
@router.get("/offers", response_model=List[PromoOfferInfo])
|
||||
@@ -160,6 +185,81 @@ async def get_promo_group_discounts(
|
||||
)
|
||||
|
||||
|
||||
@router.get("/loyalty-tiers", response_model=LoyaltyTiersResponse)
|
||||
async def get_loyalty_tiers(
|
||||
user: User = Depends(get_current_cabinet_user),
|
||||
db: AsyncSession = Depends(get_cabinet_db),
|
||||
):
|
||||
"""Get all loyalty tiers (promo groups with auto-assign thresholds) and user's progress."""
|
||||
# Get user's total spent
|
||||
total_spent_kopeks = await get_user_total_spent_kopeks(db, user.id)
|
||||
total_spent_rubles = total_spent_kopeks / 100
|
||||
|
||||
# Get user's current promo group
|
||||
await db.refresh(user, ["promo_groups"])
|
||||
current_promo_group = user.get_primary_promo_group() if hasattr(user, 'get_primary_promo_group') else None
|
||||
current_tier_name = current_promo_group.name if current_promo_group else None
|
||||
|
||||
# Get all auto-assign promo groups (sorted by threshold ascending)
|
||||
auto_groups = await get_auto_assign_promo_groups(db)
|
||||
|
||||
tiers: List[LoyaltyTierInfo] = []
|
||||
next_tier_name: Optional[str] = None
|
||||
next_tier_threshold: Optional[float] = None
|
||||
|
||||
for group in auto_groups:
|
||||
threshold_kopeks = group.auto_assign_total_spent_kopeks or 0
|
||||
threshold_rubles = threshold_kopeks / 100
|
||||
is_achieved = total_spent_kopeks >= threshold_kopeks
|
||||
is_current = current_promo_group and current_promo_group.id == group.id
|
||||
|
||||
# Get period discounts
|
||||
period_discounts = {}
|
||||
raw_period_discounts = getattr(group, "period_discounts", None)
|
||||
if isinstance(raw_period_discounts, dict):
|
||||
for key, value in raw_period_discounts.items():
|
||||
try:
|
||||
period_discounts[str(key)] = int(value)
|
||||
except (TypeError, ValueError):
|
||||
continue
|
||||
|
||||
tiers.append(
|
||||
LoyaltyTierInfo(
|
||||
id=group.id,
|
||||
name=group.name,
|
||||
threshold_rubles=threshold_rubles,
|
||||
server_discount_percent=group.server_discount_percent or 0,
|
||||
traffic_discount_percent=group.traffic_discount_percent or 0,
|
||||
device_discount_percent=group.device_discount_percent or 0,
|
||||
period_discounts=period_discounts,
|
||||
is_current=is_current,
|
||||
is_achieved=is_achieved,
|
||||
)
|
||||
)
|
||||
|
||||
# Find next tier (first not achieved)
|
||||
if not is_achieved and next_tier_name is None:
|
||||
next_tier_name = group.name
|
||||
next_tier_threshold = threshold_rubles
|
||||
|
||||
# Calculate progress to next tier
|
||||
progress_percent = 0.0
|
||||
if next_tier_threshold and next_tier_threshold > 0:
|
||||
progress_percent = min(100.0, (total_spent_rubles / next_tier_threshold) * 100)
|
||||
elif tiers and all(t.is_achieved for t in tiers):
|
||||
# All tiers achieved
|
||||
progress_percent = 100.0
|
||||
|
||||
return LoyaltyTiersResponse(
|
||||
tiers=tiers,
|
||||
current_spent_rubles=total_spent_rubles,
|
||||
current_tier_name=current_tier_name,
|
||||
next_tier_name=next_tier_name,
|
||||
next_tier_threshold_rubles=next_tier_threshold,
|
||||
progress_percent=progress_percent,
|
||||
)
|
||||
|
||||
|
||||
@router.post("/claim", response_model=ClaimOfferResponse)
|
||||
async def claim_promo_offer(
|
||||
request: ClaimOfferRequest,
|
||||
|
||||
Reference in New Issue
Block a user