Update routes/dashboard_home.py
Browse files- routes/dashboard_home.py +85 -4
routes/dashboard_home.py
CHANGED
@@ -289,6 +289,85 @@ async def get_monthly_revenue_data(target_date) -> Dict[str, Any]:
|
|
289 |
"transfer_count": transfer_data["transfer_count"]
|
290 |
}
|
291 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
292 |
@router.get("/admin/dashboard")
|
293 |
async def get_admin_dashboard(
|
294 |
user_token: str = Header(None, alias="User-key"),
|
@@ -320,7 +399,8 @@ async def get_admin_dashboard(
|
|
320 |
tasks = [
|
321 |
get_total_platform_revenue(start_timestamp, end_timestamp),
|
322 |
get_platform_transfers(start_timestamp, end_timestamp),
|
323 |
-
get_platform_users()
|
|
|
324 |
]
|
325 |
|
326 |
# Adicionar task para dados mensais se necessário
|
@@ -335,9 +415,9 @@ async def get_admin_dashboard(
|
|
335 |
|
336 |
# Extrair resultados
|
337 |
if period == "last_month":
|
338 |
-
revenue_data, transfer_data, user_data, monthly_data = results
|
339 |
else:
|
340 |
-
revenue_data, transfer_data, user_data = results
|
341 |
monthly_data = None
|
342 |
|
343 |
# Calcular divisão de receita
|
@@ -358,7 +438,8 @@ async def get_admin_dashboard(
|
|
358 |
"transfer_count": transfer_data["transfer_count"],
|
359 |
"currency": "BRL",
|
360 |
"period": period,
|
361 |
-
"users": user_data
|
|
|
362 |
}
|
363 |
|
364 |
# Adicionar dados específicos de mês apenas para período last_month
|
|
|
289 |
"transfer_count": transfer_data["transfer_count"]
|
290 |
}
|
291 |
|
292 |
+
async def get_top_stylists(start_timestamp: Optional[int] = None, end_timestamp: Optional[int] = None, limit: int = 10) -> List[Dict[str, Any]]:
|
293 |
+
"""Obtém os estilistas que mais receberam pagamentos no período"""
|
294 |
+
try:
|
295 |
+
# Obter transferências no período
|
296 |
+
query_params = {"limit": 100}
|
297 |
+
|
298 |
+
# Adicionar filtros de data se fornecidos
|
299 |
+
if start_timestamp and end_timestamp:
|
300 |
+
query_params["created"] = {"gte": start_timestamp, "lte": end_timestamp}
|
301 |
+
elif start_timestamp:
|
302 |
+
query_params["created"] = {"gte": start_timestamp}
|
303 |
+
elif end_timestamp:
|
304 |
+
query_params["created"] = {"lte": end_timestamp}
|
305 |
+
|
306 |
+
transfers = []
|
307 |
+
has_more = True
|
308 |
+
last_id = None
|
309 |
+
|
310 |
+
# Usar batch para reduzir chamadas
|
311 |
+
while has_more:
|
312 |
+
if last_id:
|
313 |
+
query_params["starting_after"] = last_id
|
314 |
+
|
315 |
+
# Usar thread para não bloquear o evento loop
|
316 |
+
transfer_list = await fetch_stripe_data(stripe.Transfer.list, expand=["data.destination"], **query_params)
|
317 |
+
transfers.extend(transfer_list.data)
|
318 |
+
|
319 |
+
has_more = transfer_list.has_more
|
320 |
+
if transfer_list.data:
|
321 |
+
last_id = transfer_list.data[-1].id
|
322 |
+
else:
|
323 |
+
has_more = False
|
324 |
+
|
325 |
+
# Agrupar transferências por estilista (destination account)
|
326 |
+
stylist_totals = {}
|
327 |
+
for transfer in transfers:
|
328 |
+
destination = transfer.destination
|
329 |
+
if destination not in stylist_totals:
|
330 |
+
stylist_totals[destination] = {
|
331 |
+
"account_id": destination,
|
332 |
+
"total_received": 0
|
333 |
+
}
|
334 |
+
stylist_totals[destination]["total_received"] += transfer.amount
|
335 |
+
|
336 |
+
# Ordenar estilistas por valor recebido
|
337 |
+
top_stylists_by_account = sorted(
|
338 |
+
stylist_totals.values(),
|
339 |
+
key=lambda x: x["total_received"],
|
340 |
+
reverse=True
|
341 |
+
)[:limit]
|
342 |
+
|
343 |
+
# Buscar informações adicionais dos estilistas no Supabase
|
344 |
+
async with aiohttp.ClientSession() as session:
|
345 |
+
top_stylists = []
|
346 |
+
for stylist_data in top_stylists_by_account:
|
347 |
+
account_id = stylist_data["account_id"]
|
348 |
+
|
349 |
+
# Buscar usuário correspondente pelo Stripe account_id
|
350 |
+
query_url = f"{SUPABASE_URL}/rest/v1/User?stripe_account_id=eq.{account_id}&select=id,name,avatar"
|
351 |
+
async with session.get(query_url, headers=SUPABASE_HEADERS) as response:
|
352 |
+
if response.status == 200:
|
353 |
+
user_data = await response.json()
|
354 |
+
if user_data and len(user_data) > 0:
|
355 |
+
# Combinar dados do Stripe com dados do Supabase
|
356 |
+
stylist_info = {
|
357 |
+
"id": user_data[0].get("id"),
|
358 |
+
"name": user_data[0].get("name", "Estilista"),
|
359 |
+
"avatar": user_data[0].get("avatar"),
|
360 |
+
"total_received": stylist_data["total_received"],
|
361 |
+
"total_transfers": stylist_totals[account_id].get("total_transfers", 1)
|
362 |
+
}
|
363 |
+
top_stylists.append(stylist_info)
|
364 |
+
|
365 |
+
return top_stylists[:limit]
|
366 |
+
|
367 |
+
except Exception as e:
|
368 |
+
logger.error(f"❌ Erro ao obter top estilistas: {str(e)}")
|
369 |
+
return []
|
370 |
+
|
371 |
@router.get("/admin/dashboard")
|
372 |
async def get_admin_dashboard(
|
373 |
user_token: str = Header(None, alias="User-key"),
|
|
|
399 |
tasks = [
|
400 |
get_total_platform_revenue(start_timestamp, end_timestamp),
|
401 |
get_platform_transfers(start_timestamp, end_timestamp),
|
402 |
+
get_platform_users(),
|
403 |
+
get_top_stylists(start_timestamp, end_timestamp, 10)
|
404 |
]
|
405 |
|
406 |
# Adicionar task para dados mensais se necessário
|
|
|
415 |
|
416 |
# Extrair resultados
|
417 |
if period == "last_month":
|
418 |
+
revenue_data, transfer_data, user_data, top_stylists, monthly_data = results
|
419 |
else:
|
420 |
+
revenue_data, transfer_data, user_data, top_stylists = results
|
421 |
monthly_data = None
|
422 |
|
423 |
# Calcular divisão de receita
|
|
|
438 |
"transfer_count": transfer_data["transfer_count"],
|
439 |
"currency": "BRL",
|
440 |
"period": period,
|
441 |
+
"users": user_data,
|
442 |
+
"top_stylists": top_stylists
|
443 |
}
|
444 |
|
445 |
# Adicionar dados específicos de mês apenas para período last_month
|