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 |
|