habulaj commited on
Commit
c854f83
·
verified ·
1 Parent(s): cb92b93

Update routes/dashboard_home.py

Browse files
Files changed (1) hide show
  1. routes/dashboard_home.py +76 -79
routes/dashboard_home.py CHANGED
@@ -250,6 +250,82 @@ async def get_platform_users() -> Dict[str, Any]:
250
  "error": str(e)
251
  }
252
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
253
  async def get_monthly_revenue_data(target_date) -> Dict[str, Any]:
254
  """Obtém o faturamento de um mês específico de forma otimizada"""
255
  ny_timezone = pytz.timezone('America/New_York')
@@ -289,85 +365,6 @@ async def get_monthly_revenue_data(target_date) -> Dict[str, Any]:
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"),
 
250
  "error": 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 de forma otimizada"""
255
+ try:
256
+ # Construir a query para obter assinaturas ativas
257
+ subscriptions_url = f"{SUPABASE_URL}/rest/v1/Subscriptions?active=eq.true&select=stylist_id"
258
+
259
+ # Adicionar filtros de data se fornecidos
260
+ if start_timestamp or end_timestamp:
261
+ date_filters = []
262
+ if start_timestamp:
263
+ start_date = datetime.fromtimestamp(start_timestamp).strftime("%Y-%m-%d")
264
+ date_filters.append(f"created_at=gte.{start_date}")
265
+ if end_timestamp:
266
+ end_date = datetime.fromtimestamp(end_timestamp).strftime("%Y-%m-%d")
267
+ date_filters.append(f"created_at=lte.{end_date}")
268
+
269
+ if date_filters:
270
+ date_query = "&".join(date_filters)
271
+ subscriptions_url = f"{subscriptions_url}&{date_query}"
272
+
273
+ # Fazer a requisição para as assinaturas
274
+ async with aiohttp.ClientSession() as session:
275
+ async with session.get(subscriptions_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
+ # Contar assinaturas por estilista
283
+ stylist_counts = {}
284
+ for subscription in subscriptions_data:
285
+ stylist_id = subscription.get("stylist_id")
286
+ if stylist_id:
287
+ stylist_counts[stylist_id] = stylist_counts.get(stylist_id, 0) + 1
288
+
289
+ # Obter IDs dos top estilistas
290
+ top_stylist_ids = sorted(stylist_counts.keys(), key=lambda x: stylist_counts[x], reverse=True)[:limit]
291
+
292
+ # Sem estilistas encontrados
293
+ if not top_stylist_ids:
294
+ return []
295
+
296
+ # Construir a query para obter detalhes dos estilistas
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
301
+ async with aiohttp.ClientSession() as session:
302
+ async with session.get(stylists_url, headers=SUPABASE_HEADERS) as response:
303
+ if response.status != 200:
304
+ logger.error(f"❌ Erro ao obter detalhes dos estilistas: {response.status}")
305
+ return []
306
+
307
+ stylists_data = await response.json()
308
+
309
+ # Combinar contagem com detalhes e ordenar por número de assinantes
310
+ result = []
311
+ for stylist in stylists_data:
312
+ stylist_id = stylist.get("id")
313
+ if stylist_id in stylist_counts:
314
+ result.append({
315
+ "id": stylist_id,
316
+ "name": stylist.get("name", "Nome não disponível"),
317
+ "avatar": stylist.get("avatar", ""),
318
+ "subscription_count": stylist_counts[stylist_id]
319
+ })
320
+
321
+ # Ordenar por número de assinantes (decrescente)
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)}")
327
+ return []
328
+
329
  async def get_monthly_revenue_data(target_date) -> Dict[str, Any]:
330
  """Obtém o faturamento de um mês específico de forma otimizada"""
331
  ny_timezone = pytz.timezone('America/New_York')
 
365
  "transfer_count": transfer_data["transfer_count"]
366
  }
367
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
368
  @router.get("/admin/dashboard")
369
  async def get_admin_dashboard(
370
  user_token: str = Header(None, alias="User-key"),