Update routes/dashboard_home.py
Browse files- routes/dashboard_home.py +119 -22
routes/dashboard_home.py
CHANGED
@@ -404,32 +404,91 @@ async def get_monthly_revenue_data(target_date) -> Dict[str, Any]:
|
|
404 |
"transfer_count": transfer_data["transfer_count"]
|
405 |
}
|
406 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
407 |
@router.get("/admin/dashboard")
|
408 |
async def get_admin_dashboard(
|
409 |
user_token: str = Header(None, alias="User-key"),
|
410 |
-
period: str = Query("
|
411 |
):
|
412 |
"""
|
413 |
Endpoint para dashboard administrativo com métricas de faturamento
|
414 |
-
e divisão entre app e estilistas - versão otimizada
|
415 |
"""
|
416 |
try:
|
417 |
# Verificar se é um administrador
|
418 |
user_id = await verify_admin_token(user_token)
|
419 |
|
420 |
-
#
|
421 |
-
|
422 |
-
now_ny = datetime.now(ny_timezone)
|
423 |
-
|
424 |
-
start_timestamp = None
|
425 |
-
end_timestamp = int(now_ny.timestamp())
|
426 |
-
|
427 |
-
if period == "last_month":
|
428 |
-
start_date = now_ny - relativedelta(months=1)
|
429 |
-
start_timestamp = int(start_date.timestamp())
|
430 |
-
elif period == "last_year":
|
431 |
-
start_date = now_ny - relativedelta(years=1)
|
432 |
-
start_timestamp = int(start_date.timestamp())
|
433 |
|
434 |
# Executar todas as chamadas em paralelo
|
435 |
tasks = [
|
@@ -439,10 +498,31 @@ async def get_admin_dashboard(
|
|
439 |
get_top_stylists(start_timestamp, end_timestamp, 10)
|
440 |
]
|
441 |
|
442 |
-
# Adicionar task para dados mensais se
|
443 |
monthly_task = None
|
444 |
-
|
445 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
446 |
monthly_task = get_monthly_revenue_data(target_date)
|
447 |
tasks.append(monthly_task)
|
448 |
|
@@ -450,11 +530,10 @@ async def get_admin_dashboard(
|
|
450 |
results = await asyncio.gather(*tasks)
|
451 |
|
452 |
# Extrair resultados
|
453 |
-
if period
|
454 |
revenue_data, transfer_data, user_data, top_stylists, monthly_data = results
|
455 |
else:
|
456 |
revenue_data, transfer_data, user_data, top_stylists = results
|
457 |
-
monthly_data = None
|
458 |
|
459 |
# Calcular divisão de receita
|
460 |
revenue_share = get_app_revenue_share(
|
@@ -478,9 +557,27 @@ async def get_admin_dashboard(
|
|
478 |
"top_stylists": top_stylists
|
479 |
}
|
480 |
|
481 |
-
# Adicionar dados específicos de mês
|
482 |
-
if period
|
483 |
response["monthly_data"] = monthly_data
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
484 |
|
485 |
return response
|
486 |
|
|
|
404 |
"transfer_count": transfer_data["transfer_count"]
|
405 |
}
|
406 |
|
407 |
+
# Função auxiliar para lidar com os períodos específicos
|
408 |
+
def get_period_timestamps(period: str) -> Tuple[Optional[int], Optional[int]]:
|
409 |
+
"""Retorna timestamps inicial e final baseados no período especificado"""
|
410 |
+
ny_timezone = pytz.timezone('America/New_York')
|
411 |
+
now_ny = datetime.now(ny_timezone)
|
412 |
+
current_year = now_ny.year
|
413 |
+
|
414 |
+
# Inicializar timestamps
|
415 |
+
start_timestamp = None
|
416 |
+
end_timestamp = int(now_ny.timestamp())
|
417 |
+
|
418 |
+
# Lidar com os meses específicos
|
419 |
+
months = {
|
420 |
+
'January': 1, 'February': 2, 'March': 3, 'April': 4,
|
421 |
+
'May': 5, 'June': 6, 'July': 7, 'August': 8,
|
422 |
+
'September': 9, 'October': 10, 'November': 11, 'December': 12
|
423 |
+
}
|
424 |
+
|
425 |
+
if period in months:
|
426 |
+
# Período para um mês específico do ano atual
|
427 |
+
month_num = months[period]
|
428 |
+
|
429 |
+
# Se o mês solicitado ainda não chegou neste ano, use o ano anterior
|
430 |
+
if month_num > now_ny.month:
|
431 |
+
year = current_year - 1
|
432 |
+
else:
|
433 |
+
year = current_year
|
434 |
+
|
435 |
+
# Definir início e fim do mês
|
436 |
+
month_start = datetime(year, month_num, 1, tzinfo=ny_timezone)
|
437 |
+
if month_num == 12:
|
438 |
+
month_end = datetime(year + 1, 1, 1, tzinfo=ny_timezone) - timedelta(seconds=1)
|
439 |
+
else:
|
440 |
+
month_end = datetime(year, month_num + 1, 1, tzinfo=ny_timezone) - timedelta(seconds=1)
|
441 |
+
|
442 |
+
start_timestamp = int(month_start.timestamp())
|
443 |
+
end_timestamp = int(month_end.timestamp())
|
444 |
+
|
445 |
+
elif period == "All Year":
|
446 |
+
# Período para o ano atual inteiro
|
447 |
+
year_start = datetime(current_year, 1, 1, tzinfo=ny_timezone)
|
448 |
+
year_end = datetime(current_year + 1, 1, 1, tzinfo=ny_timezone) - timedelta(seconds=1)
|
449 |
+
|
450 |
+
start_timestamp = int(year_start.timestamp())
|
451 |
+
end_timestamp = int(year_end.timestamp())
|
452 |
+
|
453 |
+
# Se estamos no início do ano, pode ser útil mostrar dados do ano anterior também
|
454 |
+
if now_ny.month <= 2:
|
455 |
+
year_start = datetime(current_year - 1, 1, 1, tzinfo=ny_timezone)
|
456 |
+
start_timestamp = int(year_start.timestamp())
|
457 |
+
|
458 |
+
# Períodos legados (manter para compatibilidade)
|
459 |
+
elif period == "last_month":
|
460 |
+
start_date = now_ny - relativedelta(months=1)
|
461 |
+
start_timestamp = int(start_date.timestamp())
|
462 |
+
elif period == "last_year":
|
463 |
+
start_date = now_ny - relativedelta(years=1)
|
464 |
+
start_timestamp = int(start_date.timestamp())
|
465 |
+
|
466 |
+
return start_timestamp, end_timestamp
|
467 |
+
|
468 |
+
# Helper function to identify if we need specific month data
|
469 |
+
def is_specific_month(period: str) -> bool:
|
470 |
+
"""Verifica se o período solicitado é um mês específico"""
|
471 |
+
months = [
|
472 |
+
'January', 'February', 'March', 'April', 'May', 'June',
|
473 |
+
'July', 'August', 'September', 'October', 'November', 'December'
|
474 |
+
]
|
475 |
+
return period in months
|
476 |
+
|
477 |
@router.get("/admin/dashboard")
|
478 |
async def get_admin_dashboard(
|
479 |
user_token: str = Header(None, alias="User-key"),
|
480 |
+
period: str = Query("All Year", description="Período: All Year, January, February, etc.")
|
481 |
):
|
482 |
"""
|
483 |
Endpoint para dashboard administrativo com métricas de faturamento
|
484 |
+
e divisão entre app e estilistas - versão otimizada com seleção de meses
|
485 |
"""
|
486 |
try:
|
487 |
# Verificar se é um administrador
|
488 |
user_id = await verify_admin_token(user_token)
|
489 |
|
490 |
+
# Obter timestamps baseados no período
|
491 |
+
start_timestamp, end_timestamp = get_period_timestamps(period)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
492 |
|
493 |
# Executar todas as chamadas em paralelo
|
494 |
tasks = [
|
|
|
498 |
get_top_stylists(start_timestamp, end_timestamp, 10)
|
499 |
]
|
500 |
|
501 |
+
# Adicionar task para dados mensais se for um mês específico
|
502 |
monthly_task = None
|
503 |
+
monthly_data = None
|
504 |
+
|
505 |
+
if is_specific_month(period):
|
506 |
+
# Obter dados mensais para o mês solicitado
|
507 |
+
ny_timezone = pytz.timezone('America/New_York')
|
508 |
+
now_ny = datetime.now(ny_timezone)
|
509 |
+
current_year = now_ny.year
|
510 |
+
|
511 |
+
# Obter número do mês
|
512 |
+
months = {
|
513 |
+
'January': 1, 'February': 2, 'March': 3, 'April': 4,
|
514 |
+
'May': 5, 'June': 6, 'July': 7, 'August': 8,
|
515 |
+
'September': 9, 'October': 10, 'November': 11, 'December': 12
|
516 |
+
}
|
517 |
+
month_num = months[period]
|
518 |
+
|
519 |
+
# Se o mês ainda não chegou neste ano, use o ano anterior
|
520 |
+
if month_num > now_ny.month:
|
521 |
+
year = current_year - 1
|
522 |
+
else:
|
523 |
+
year = current_year
|
524 |
+
|
525 |
+
target_date = datetime(year, month_num, 1, tzinfo=ny_timezone)
|
526 |
monthly_task = get_monthly_revenue_data(target_date)
|
527 |
tasks.append(monthly_task)
|
528 |
|
|
|
530 |
results = await asyncio.gather(*tasks)
|
531 |
|
532 |
# Extrair resultados
|
533 |
+
if is_specific_month(period):
|
534 |
revenue_data, transfer_data, user_data, top_stylists, monthly_data = results
|
535 |
else:
|
536 |
revenue_data, transfer_data, user_data, top_stylists = results
|
|
|
537 |
|
538 |
# Calcular divisão de receita
|
539 |
revenue_share = get_app_revenue_share(
|
|
|
557 |
"top_stylists": top_stylists
|
558 |
}
|
559 |
|
560 |
+
# Adicionar dados específicos de mês
|
561 |
+
if is_specific_month(period) and monthly_data:
|
562 |
response["monthly_data"] = monthly_data
|
563 |
+
|
564 |
+
# Para "All Year", adicionar dados mensais para visualização
|
565 |
+
if period == "All Year":
|
566 |
+
# Obter dados para cada mês do ano atual
|
567 |
+
ny_timezone = pytz.timezone('America/New_York')
|
568 |
+
now_ny = datetime.now(ny_timezone)
|
569 |
+
current_year = now_ny.year
|
570 |
+
|
571 |
+
monthly_tasks = []
|
572 |
+
for month in range(1, 13):
|
573 |
+
# Só incluir meses que já passaram ou o mês atual
|
574 |
+
if month <= now_ny.month:
|
575 |
+
target_date = datetime(current_year, month, 1, tzinfo=ny_timezone)
|
576 |
+
monthly_tasks.append(get_monthly_revenue_data(target_date))
|
577 |
+
|
578 |
+
if monthly_tasks:
|
579 |
+
monthly_results = await asyncio.gather(*monthly_tasks)
|
580 |
+
response["year_data"] = monthly_results
|
581 |
|
582 |
return response
|
583 |
|