Add gamification trust analytics polish

This commit is contained in:
VPN SaaS Dev
2026-05-12 20:15:24 +09:00
parent 26875e396c
commit 7fd4ab768f
5 changed files with 95 additions and 2 deletions

View File

@@ -22,6 +22,7 @@ from app.services.scoring import (
compute_service_center_score,
compute_vehicle_score,
evaluate_garage_achievements,
record_engagement_event,
)
router = APIRouter(tags=["gamification"])
@@ -64,6 +65,13 @@ async def vehicle_score(
):
car = await ensure_vehicle_owner_or_access(session, vehicle_id, current_user)
score = await compute_vehicle_score(session, car)
await record_engagement_event(
session,
event_type="vehicle_score_viewed",
user_id=current_user.id,
vehicle_id=vehicle_id,
metadata={"completeness_score": score.completeness_score},
)
await session.commit()
await session.refresh(score)
return score
@@ -82,6 +90,12 @@ async def vehicle_timeline(
limit = min(limit, 200)
offset = max(offset, 0)
car = await ensure_vehicle_owner_or_access(session, vehicle_id, current_user)
await record_engagement_event(
session,
event_type="vehicle_timeline_viewed",
user_id=current_user.id,
vehicle_id=vehicle_id,
)
fuel_entries = list((await session.execute(select(FuelEntry).where(FuelEntry.car_id == car.id))).scalars())
service_entries = list((await session.execute(select(ServiceEntry).where(ServiceEntry.car_id == car.id))).scalars())
visits = list((await session.execute(select(ServiceVisit).where(ServiceVisit.vehicle_id == car.id))).scalars())
@@ -179,6 +193,13 @@ async def service_center_trust_score(
raise HTTPException(status_code=404, detail="Service center not found")
await ensure_service_employee(session, service_center_id, current_user)
score = await compute_service_center_score(session, center)
await record_engagement_event(
session,
event_type="service_trust_score_viewed",
user_id=current_user.id,
service_center_id=service_center_id,
metadata={"trust_score": score.trust_score, "trust_level": score.trust_level},
)
await session.commit()
await session.refresh(score)
return score

View File

@@ -1,7 +1,7 @@
from __future__ import annotations
from dataclasses import dataclass
from datetime import date
from datetime import UTC, date, datetime, timedelta
from decimal import Decimal
from sqlalchemy import func, select
@@ -327,6 +327,41 @@ async def unlock_achievement(
)
async def record_engagement_event(
session: AsyncSession,
*,
event_type: str,
user_id: int | None = None,
vehicle_id: int | None = None,
service_center_id: int | None = None,
metadata: dict | None = None,
cooldown_minutes: int = 360,
) -> None:
since = datetime.now(UTC) - timedelta(minutes=cooldown_minutes)
result = await session.execute(
select(EngagementEvent).where(
EngagementEvent.event_type == event_type,
EngagementEvent.user_id.is_(None) if user_id is None else EngagementEvent.user_id == user_id,
EngagementEvent.vehicle_id.is_(None) if vehicle_id is None else EngagementEvent.vehicle_id == vehicle_id,
EngagementEvent.service_center_id.is_(None)
if service_center_id is None
else EngagementEvent.service_center_id == service_center_id,
EngagementEvent.created_at >= since,
)
)
if result.scalar_one_or_none() is not None:
return
session.add(
EngagementEvent(
user_id=user_id,
vehicle_id=vehicle_id,
service_center_id=service_center_id,
event_type=event_type,
metadata_json=metadata,
)
)
async def evaluate_vehicle_achievements(
session: AsyncSession,
car: Car,