init
parent
cb00f43e98
commit
32601f34b5
@ -0,0 +1,222 @@
|
|||||||
|
from datetime import datetime, timedelta
|
||||||
|
from typing import Any, Dict, List, Optional
|
||||||
|
|
||||||
|
from extensions.ext_database import db
|
||||||
|
from models import Conversation, EndUser, Message
|
||||||
|
from sqlalchemy import and_, distinct, func
|
||||||
|
|
||||||
|
|
||||||
|
class StatsService:
|
||||||
|
@staticmethod
|
||||||
|
def get_risk_stats(
|
||||||
|
start_date: datetime, end_date: datetime, app_id: Optional[str] = None, organization_id: Optional[str] = None
|
||||||
|
) -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
Get statistics about high risk users
|
||||||
|
|
||||||
|
Args:
|
||||||
|
start_date: The start date for the statistics
|
||||||
|
end_date: The end date for the statistics
|
||||||
|
app_id: Optional app ID to filter users by
|
||||||
|
organization_id: Optional organization ID to filter users by
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Dictionary containing high risk user count and changes
|
||||||
|
"""
|
||||||
|
# Build query with filters
|
||||||
|
high_risk_query = db.session.query(EndUser).filter(
|
||||||
|
EndUser.health_status == 'critical', EndUser.updated_at >= start_date, EndUser.updated_at <= end_date
|
||||||
|
)
|
||||||
|
total_query = db.session.query(EndUser).filter(EndUser.updated_at >= start_date, EndUser.updated_at <= end_date)
|
||||||
|
|
||||||
|
# Apply app_id filter if provided
|
||||||
|
if app_id:
|
||||||
|
high_risk_query = high_risk_query.filter(EndUser.app_id == app_id)
|
||||||
|
total_query = total_query.filter(EndUser.app_id == app_id)
|
||||||
|
|
||||||
|
# Apply organization_id filter if provided
|
||||||
|
if organization_id:
|
||||||
|
high_risk_query = high_risk_query.filter(EndUser.organization_id == organization_id)
|
||||||
|
total_query = total_query.filter(EndUser.organization_id == organization_id)
|
||||||
|
|
||||||
|
high_risk_count = high_risk_query.count()
|
||||||
|
total_count = total_query.count()
|
||||||
|
|
||||||
|
# Get yesterday's count
|
||||||
|
yesterday = end_date - timedelta(days=1)
|
||||||
|
yesterday_query = db.session.query(EndUser).filter(
|
||||||
|
EndUser.health_status == 'critical', EndUser.updated_at <= yesterday
|
||||||
|
)
|
||||||
|
|
||||||
|
# Apply app_id filter if provided
|
||||||
|
if app_id:
|
||||||
|
yesterday_query = yesterday_query.filter(EndUser.app_id == app_id)
|
||||||
|
|
||||||
|
# Apply organization_id filter if provided
|
||||||
|
if organization_id:
|
||||||
|
yesterday_query = yesterday_query.filter(EndUser.organization_id == organization_id)
|
||||||
|
|
||||||
|
yesterday_high_risk_count = yesterday_query.count()
|
||||||
|
|
||||||
|
# Get last week's count
|
||||||
|
last_week = end_date - timedelta(days=7)
|
||||||
|
last_week_query = db.session.query(EndUser).filter(
|
||||||
|
EndUser.health_status == 'critical', EndUser.updated_at <= last_week
|
||||||
|
)
|
||||||
|
|
||||||
|
# Apply app_id filter if provided
|
||||||
|
if app_id:
|
||||||
|
last_week_query = last_week_query.filter(EndUser.app_id == app_id)
|
||||||
|
|
||||||
|
# Apply organization_id filter if provided
|
||||||
|
if organization_id:
|
||||||
|
last_week_query = last_week_query.filter(EndUser.organization_id == organization_id)
|
||||||
|
|
||||||
|
last_week_high_risk_count = last_week_query.count()
|
||||||
|
|
||||||
|
# Calculate changes
|
||||||
|
from_yesterday = high_risk_count - yesterday_high_risk_count
|
||||||
|
from_last_week = high_risk_count - last_week_high_risk_count
|
||||||
|
|
||||||
|
return {
|
||||||
|
"high_risk_count": high_risk_count,
|
||||||
|
"high_risk_percentage": round(high_risk_count / total_count, 2),
|
||||||
|
"daily_changes": {"from_yesterday": from_yesterday, "from_last_week": from_last_week},
|
||||||
|
}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_user_stats(
|
||||||
|
start_date: datetime, end_date: datetime, app_id: Optional[str] = None, organization_id: Optional[str] = None
|
||||||
|
) -> Dict[str, List[Dict[str, Any]]]:
|
||||||
|
"""
|
||||||
|
Get user statistics for a date range
|
||||||
|
|
||||||
|
Args:
|
||||||
|
start_date: The start date for the statistics
|
||||||
|
end_date: The end date for the statistics
|
||||||
|
app_id: Optional app ID to filter users by
|
||||||
|
organization_id: Optional organization ID to filter users by
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Dictionary containing daily user statistics
|
||||||
|
"""
|
||||||
|
# Calculate date range
|
||||||
|
date_range = []
|
||||||
|
current_date = start_date
|
||||||
|
while current_date <= end_date:
|
||||||
|
date_range.append(current_date.strftime('%Y-%m-%d'))
|
||||||
|
current_date += timedelta(days=1)
|
||||||
|
|
||||||
|
daily_stats = []
|
||||||
|
|
||||||
|
for date_str in date_range:
|
||||||
|
date = datetime.strptime(date_str, '%Y-%m-%d')
|
||||||
|
next_date = date + timedelta(days=1)
|
||||||
|
|
||||||
|
# Count active users (users who had a conversation on this date)
|
||||||
|
active_users_query = db.session.query(distinct(Conversation.from_end_user_id)).filter(
|
||||||
|
Conversation.created_at >= date, Conversation.created_at < next_date
|
||||||
|
)
|
||||||
|
|
||||||
|
# Apply app_id filter if provided
|
||||||
|
if app_id:
|
||||||
|
active_users_query = active_users_query.filter(Conversation.app_id == app_id)
|
||||||
|
|
||||||
|
# Apply organization filters for conversations
|
||||||
|
if organization_id:
|
||||||
|
active_users_query = active_users_query.filter(Conversation.organization_id == organization_id)
|
||||||
|
|
||||||
|
active_users = active_users_query.count()
|
||||||
|
|
||||||
|
# Count new users (users who were created on this date)
|
||||||
|
new_users_query = db.session.query(EndUser).filter(
|
||||||
|
EndUser.created_at >= date, EndUser.created_at < next_date
|
||||||
|
)
|
||||||
|
|
||||||
|
# Apply app_id filter if provided
|
||||||
|
if app_id:
|
||||||
|
new_users_query = new_users_query.filter(EndUser.app_id == app_id)
|
||||||
|
|
||||||
|
# Apply organization_id filter if provided
|
||||||
|
if organization_id:
|
||||||
|
new_users_query = new_users_query.filter(EndUser.organization_id == organization_id)
|
||||||
|
|
||||||
|
new_users = new_users_query.count()
|
||||||
|
|
||||||
|
daily_stats.append({"date": date_str, "active_users": active_users, "new_users": new_users})
|
||||||
|
|
||||||
|
return {"daily_stats": daily_stats}
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_conversation_stats(
|
||||||
|
start_date: datetime, end_date: datetime, app_id: Optional[str] = None, organization_id: Optional[str] = None
|
||||||
|
) -> Dict[str, List[Dict[str, Any]]]:
|
||||||
|
"""
|
||||||
|
Get conversation statistics for a date range
|
||||||
|
|
||||||
|
Args:
|
||||||
|
start_date: The start date for the statistics
|
||||||
|
end_date: The end date for the statistics
|
||||||
|
app_id: Optional app ID to filter conversations by
|
||||||
|
organization_id: Optional organization ID to filter conversations by
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Dictionary containing daily conversation statistics
|
||||||
|
"""
|
||||||
|
# Calculate date range
|
||||||
|
date_range = []
|
||||||
|
current_date = start_date
|
||||||
|
while current_date <= end_date:
|
||||||
|
date_range.append(current_date.strftime('%Y-%m-%d'))
|
||||||
|
current_date += timedelta(days=1)
|
||||||
|
|
||||||
|
daily_stats = []
|
||||||
|
|
||||||
|
for date_str in date_range:
|
||||||
|
date = datetime.strptime(date_str, '%Y-%m-%d')
|
||||||
|
next_date = date + timedelta(days=1)
|
||||||
|
|
||||||
|
# Count total conversations for this date
|
||||||
|
conv_query = db.session.query(Conversation).filter(
|
||||||
|
Conversation.created_at >= date, Conversation.created_at < next_date
|
||||||
|
)
|
||||||
|
|
||||||
|
# Apply app_id filter if provided
|
||||||
|
if app_id:
|
||||||
|
conv_query = conv_query.filter(Conversation.app_id == app_id)
|
||||||
|
|
||||||
|
# Apply organization_id filter if provided
|
||||||
|
if organization_id:
|
||||||
|
conv_query = conv_query.filter(Conversation.organization_id == organization_id)
|
||||||
|
|
||||||
|
total_conversations = conv_query.count()
|
||||||
|
|
||||||
|
# Count unique users who had conversations on this date
|
||||||
|
unique_users_query = db.session.query(distinct(Conversation.from_end_user_id)).filter(
|
||||||
|
Conversation.created_at >= date, Conversation.created_at < next_date
|
||||||
|
)
|
||||||
|
|
||||||
|
# Apply app_id filter if provided
|
||||||
|
if app_id:
|
||||||
|
unique_users_query = unique_users_query.filter(Conversation.app_id == app_id)
|
||||||
|
|
||||||
|
# Apply organization_id filter if provided
|
||||||
|
if organization_id:
|
||||||
|
unique_users_query = unique_users_query.filter(Conversation.organization_id == organization_id)
|
||||||
|
|
||||||
|
unique_users = unique_users_query.count()
|
||||||
|
|
||||||
|
# Calculate average conversations per user
|
||||||
|
avg_conversations_per_user = 0
|
||||||
|
if unique_users > 0:
|
||||||
|
avg_conversations_per_user = round(total_conversations / unique_users, 2)
|
||||||
|
|
||||||
|
daily_stats.append(
|
||||||
|
{
|
||||||
|
"date": date_str,
|
||||||
|
"total_conversations": total_conversations,
|
||||||
|
"avg_conversations_per_user": avg_conversations_per_user,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
return {"daily_stats": daily_stats}
|
||||||
Loading…
Reference in New Issue