Update routes/dashboard_home.py
Browse files- routes/dashboard_home.py +42 -24
routes/dashboard_home.py
CHANGED
@@ -251,10 +251,10 @@ async def get_platform_users() -> Dict[str, Any]:
|
|
251 |
}
|
252 |
|
253 |
async def get_top_stylists(start_timestamp: Optional[int] = None, end_timestamp: Optional[int] = None, limit: int = 10) -> List[Dict[str, Any]]:
|
254 |
-
"""Obtém os estilistas com mais assinantes ativos de forma otimizada"""
|
255 |
try:
|
256 |
-
#
|
257 |
-
|
258 |
|
259 |
# Adicionar filtros de data se fornecidos
|
260 |
if start_timestamp or end_timestamp:
|
@@ -268,33 +268,50 @@ async def get_top_stylists(start_timestamp: Optional[int] = None, end_timestamp:
|
|
268 |
|
269 |
if date_filters:
|
270 |
date_query = "&".join(date_filters)
|
271 |
-
|
272 |
|
273 |
-
# Fazer a requisição para as assinaturas
|
274 |
async with aiohttp.ClientSession() as session:
|
275 |
-
async with session.get(
|
276 |
if response.status != 200:
|
277 |
logger.error(f"❌ Erro ao obter assinaturas: {response.status}")
|
278 |
return []
|
279 |
|
280 |
subscriptions_data = await response.json()
|
281 |
|
282 |
-
#
|
283 |
-
|
284 |
for subscription in subscriptions_data:
|
285 |
stylist_id = subscription.get("stylist_id")
|
286 |
-
|
287 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
288 |
|
289 |
-
#
|
290 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
291 |
|
292 |
# Sem estilistas encontrados
|
293 |
if not top_stylist_ids:
|
294 |
return []
|
295 |
|
296 |
-
#
|
297 |
-
stylists_ids_str = ",".join([f"eq.{id}" for id in top_stylist_ids])
|
298 |
stylists_url = f"{SUPABASE_URL}/rest/v1/User?id=in.({','.join(top_stylist_ids)})&select=id,name,avatar"
|
299 |
|
300 |
# Obter detalhes dos estilistas
|
@@ -306,21 +323,22 @@ async def get_top_stylists(start_timestamp: Optional[int] = None, end_timestamp:
|
|
306 |
|
307 |
stylists_data = await response.json()
|
308 |
|
309 |
-
#
|
|
|
|
|
|
|
310 |
result = []
|
311 |
-
for
|
312 |
-
stylist_id
|
313 |
-
if stylist_id in stylist_counts:
|
314 |
result.append({
|
315 |
"id": stylist_id,
|
316 |
-
"name":
|
317 |
-
"avatar":
|
318 |
-
"
|
|
|
319 |
})
|
320 |
|
321 |
-
|
322 |
-
result.sort(key=lambda x: x["subscription_count"], reverse=True)
|
323 |
-
return result[:limit] # Limitar ao número solicitado
|
324 |
|
325 |
except Exception as e:
|
326 |
logger.error(f"❌ Erro ao obter top estilistas: {str(e)}")
|
|
|
251 |
}
|
252 |
|
253 |
async def get_top_stylists(start_timestamp: Optional[int] = None, end_timestamp: Optional[int] = None, limit: int = 10) -> List[Dict[str, Any]]:
|
254 |
+
"""Obtém os estilistas com mais assinantes ativos e totais de forma otimizada"""
|
255 |
try:
|
256 |
+
# Obter todas as assinaturas
|
257 |
+
base_url = f"{SUPABASE_URL}/rest/v1/Subscriptions?select=stylist_id,active,created_at"
|
258 |
|
259 |
# Adicionar filtros de data se fornecidos
|
260 |
if start_timestamp or end_timestamp:
|
|
|
268 |
|
269 |
if date_filters:
|
270 |
date_query = "&".join(date_filters)
|
271 |
+
base_url = f"{base_url}&{date_query}"
|
272 |
|
273 |
+
# Fazer a requisição para obter todas as assinaturas
|
274 |
async with aiohttp.ClientSession() as session:
|
275 |
+
async with session.get(base_url, headers=SUPABASE_HEADERS) as response:
|
276 |
if response.status != 200:
|
277 |
logger.error(f"❌ Erro ao obter assinaturas: {response.status}")
|
278 |
return []
|
279 |
|
280 |
subscriptions_data = await response.json()
|
281 |
|
282 |
+
# Contadores para assinaturas ativas e totais por estilista
|
283 |
+
stylists_stats = {}
|
284 |
for subscription in subscriptions_data:
|
285 |
stylist_id = subscription.get("stylist_id")
|
286 |
+
is_active = subscription.get("active", False)
|
287 |
+
|
288 |
+
if stylist_id not in stylists_stats:
|
289 |
+
stylists_stats[stylist_id] = {
|
290 |
+
"active_count": 0,
|
291 |
+
"total_count": 0
|
292 |
+
}
|
293 |
+
|
294 |
+
# Incrementar contadores
|
295 |
+
stylists_stats[stylist_id]["total_count"] += 1
|
296 |
+
if is_active:
|
297 |
+
stylists_stats[stylist_id]["active_count"] += 1
|
298 |
|
299 |
+
# Se não houver estilistas, retornar lista vazia
|
300 |
+
if not stylists_stats:
|
301 |
+
return []
|
302 |
+
|
303 |
+
# Ordenar estilistas por número de assinaturas ativas (decrescente)
|
304 |
+
top_stylist_ids = sorted(
|
305 |
+
stylists_stats.keys(),
|
306 |
+
key=lambda x: stylists_stats[x]["active_count"],
|
307 |
+
reverse=True
|
308 |
+
)[:limit]
|
309 |
|
310 |
# Sem estilistas encontrados
|
311 |
if not top_stylist_ids:
|
312 |
return []
|
313 |
|
314 |
+
# Obter detalhes dos estilistas em uma única chamada
|
|
|
315 |
stylists_url = f"{SUPABASE_URL}/rest/v1/User?id=in.({','.join(top_stylist_ids)})&select=id,name,avatar"
|
316 |
|
317 |
# Obter detalhes dos estilistas
|
|
|
323 |
|
324 |
stylists_data = await response.json()
|
325 |
|
326 |
+
# Mapear os IDs para facilitar o acesso
|
327 |
+
stylists_map = {stylist["id"]: stylist for stylist in stylists_data}
|
328 |
+
|
329 |
+
# Combinar estatísticas com detalhes dos estilistas
|
330 |
result = []
|
331 |
+
for stylist_id in top_stylist_ids:
|
332 |
+
if stylist_id in stylists_map:
|
|
|
333 |
result.append({
|
334 |
"id": stylist_id,
|
335 |
+
"name": stylists_map[stylist_id].get("name", "Nome não disponível"),
|
336 |
+
"avatar": stylists_map[stylist_id].get("avatar", ""),
|
337 |
+
"active_subscriptions": stylists_stats[stylist_id]["active_count"],
|
338 |
+
"total_subscriptions": stylists_stats[stylist_id]["total_count"]
|
339 |
})
|
340 |
|
341 |
+
return result
|
|
|
|
|
342 |
|
343 |
except Exception as e:
|
344 |
logger.error(f"❌ Erro ao obter top estilistas: {str(e)}")
|