Update routes/subscription.py
Browse files- routes/subscription.py +56 -62
routes/subscription.py
CHANGED
@@ -5,6 +5,7 @@ from datetime import datetime
|
|
5 |
import pytz
|
6 |
import os
|
7 |
import requests
|
|
|
8 |
import jwt
|
9 |
from fastapi import APIRouter, HTTPException, Request, Header
|
10 |
from pydantic import BaseModel
|
@@ -474,7 +475,7 @@ def cancel_subscription(data: CancelSubscriptionRequest):
|
|
474 |
raise HTTPException(status_code=500, detail=str(e))
|
475 |
|
476 |
@router.post("/check_subscription")
|
477 |
-
def check_subscription(
|
478 |
data: CheckSubscriptionRequest,
|
479 |
user_token: str = Header(None, alias="User-key")
|
480 |
):
|
@@ -486,9 +487,9 @@ def check_subscription(
|
|
486 |
user_id = verify_token(user_token)
|
487 |
|
488 |
# 🔹 Buscar o stripe_id do usuário no Supabase
|
489 |
-
response_user =
|
490 |
f"{SUPABASE_URL}/rest/v1/User?id=eq.{user_id}",
|
491 |
-
|
492 |
)
|
493 |
user_data = response_user.json()
|
494 |
if not user_data:
|
@@ -499,46 +500,28 @@ def check_subscription(
|
|
499 |
raise HTTPException(status_code=404, detail="Stripe customer not found for user")
|
500 |
|
501 |
# 🔹 Buscar todas as assinaturas do cliente (ativas, canceladas, expiradas, etc.)
|
502 |
-
subscriptions =
|
|
|
503 |
customer=user_stripe_id,
|
504 |
expand=["data.items"]
|
505 |
)
|
506 |
|
507 |
logger.info(f"Stripe response data: {subscriptions}")
|
508 |
|
509 |
-
if not subscriptions or
|
510 |
# Se não houver assinaturas para o cliente, desativa as assinaturas associadas ao estilista no banco de dados
|
511 |
logger.info(f"No active subscription found for user {user_id}. Deactivating all subscriptions for stylist {data.stylist_id}.")
|
512 |
|
513 |
# 🔹 Buscar todas as assinaturas do estilista no banco de dados para este cliente
|
514 |
-
response_subscriptions =
|
515 |
f"{SUPABASE_URL}/rest/v1/Subscriptions?customer_id=eq.{user_id}&stylist_id=eq.{data.stylist_id}",
|
516 |
-
|
517 |
)
|
518 |
if response_subscriptions.status_code == 200:
|
519 |
subscriptions_data = response_subscriptions.json()
|
520 |
-
|
521 |
-
|
522 |
-
|
523 |
-
|
524 |
-
# Atualiza todas as assinaturas do estilista no banco de dados de uma vez
|
525 |
-
if update_data:
|
526 |
-
update_response = requests.patch(
|
527 |
-
f"{SUPABASE_URL}/rest/v1/Subscriptions",
|
528 |
-
headers=SUPABASE_HEADERS,
|
529 |
-
json=update_data
|
530 |
-
)
|
531 |
-
if update_response.status_code == 200:
|
532 |
-
logger.info(f"✅ All subscriptions for stylist {data.stylist_id} deactivated successfully.")
|
533 |
-
else:
|
534 |
-
logger.error(f"❌ Failed to deactivate subscriptions for stylist {data.stylist_id}.")
|
535 |
-
|
536 |
-
# Retorna as assinaturas desativadas no banco
|
537 |
-
return {
|
538 |
-
"status": "inactive",
|
539 |
-
"message": "No active subscription found for stylist.",
|
540 |
-
"subscriptions_updated": subscriptions_data
|
541 |
-
}
|
542 |
else:
|
543 |
logger.error(f"❌ Failed to fetch subscriptions from Supabase for stylist {data.stylist_id} and user {user_id}.")
|
544 |
|
@@ -578,17 +561,13 @@ def check_subscription(
|
|
578 |
"canceled_date": canceled_at_date
|
579 |
}
|
580 |
|
581 |
-
|
582 |
f"{SUPABASE_URL}/rest/v1/Subscriptions",
|
583 |
-
|
584 |
-
json=subscription_data
|
|
|
585 |
)
|
586 |
|
587 |
-
if response_subscription.status_code == 201:
|
588 |
-
logger.info(f"✅ Subscription updated successfully for user {user_id}")
|
589 |
-
else:
|
590 |
-
logger.error(f"❌ Failed to update subscription: {response_subscription.status_code} - {response_subscription.text}")
|
591 |
-
|
592 |
# Retorna informações sobre a assinatura sincronizada
|
593 |
return {
|
594 |
"status": status,
|
@@ -604,38 +583,53 @@ def check_subscription(
|
|
604 |
logger.info(f"No active subscription found for stylist {data.stylist_id}. Deactivating all subscriptions for this stylist.")
|
605 |
|
606 |
# 🔹 Buscar todas as assinaturas do estilista no banco de dados
|
607 |
-
response_subscriptions =
|
608 |
f"{SUPABASE_URL}/rest/v1/Subscriptions?stylist_id=eq.{data.stylist_id}",
|
609 |
-
|
610 |
)
|
611 |
if response_subscriptions.status_code == 200:
|
612 |
subscriptions_data = response_subscriptions.json()
|
613 |
-
|
614 |
-
|
615 |
-
|
616 |
-
|
617 |
-
|
618 |
-
|
619 |
-
|
620 |
-
f"{SUPABASE_URL}/rest/v1/Subscriptions",
|
621 |
-
headers=SUPABASE_HEADERS,
|
622 |
-
json=update_data
|
623 |
-
)
|
624 |
-
if update_response.status_code == 200:
|
625 |
-
logger.info(f"✅ All subscriptions for stylist {data.stylist_id} deactivated successfully.")
|
626 |
-
else:
|
627 |
-
logger.error(f"❌ Failed to deactivate subscriptions for stylist {data.stylist_id}.")
|
628 |
-
|
629 |
-
# Retorna as assinaturas desativadas no banco
|
630 |
-
return {
|
631 |
-
"status": "inactive",
|
632 |
-
"message": "No active subscription found for stylist.",
|
633 |
-
"subscriptions_updated": subscriptions_data
|
634 |
-
}
|
635 |
|
636 |
except stripe.error.StripeError as e:
|
637 |
logger.error(f"Stripe error: {str(e)}")
|
638 |
raise HTTPException(status_code=500, detail=f"Stripe error: {str(e)}")
|
639 |
except Exception as e:
|
640 |
logger.error(f"Error checking subscription: {str(e)}")
|
641 |
-
raise HTTPException(status_code=500, detail="Error checking subscription.")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
5 |
import pytz
|
6 |
import os
|
7 |
import requests
|
8 |
+
import asyncio
|
9 |
import jwt
|
10 |
from fastapi import APIRouter, HTTPException, Request, Header
|
11 |
from pydantic import BaseModel
|
|
|
475 |
raise HTTPException(status_code=500, detail=str(e))
|
476 |
|
477 |
@router.post("/check_subscription")
|
478 |
+
async def check_subscription(
|
479 |
data: CheckSubscriptionRequest,
|
480 |
user_token: str = Header(None, alias="User-key")
|
481 |
):
|
|
|
487 |
user_id = verify_token(user_token)
|
488 |
|
489 |
# 🔹 Buscar o stripe_id do usuário no Supabase
|
490 |
+
response_user = await async_request(
|
491 |
f"{SUPABASE_URL}/rest/v1/User?id=eq.{user_id}",
|
492 |
+
SUPABASE_HEADERS
|
493 |
)
|
494 |
user_data = response_user.json()
|
495 |
if not user_data:
|
|
|
500 |
raise HTTPException(status_code=404, detail="Stripe customer not found for user")
|
501 |
|
502 |
# 🔹 Buscar todas as assinaturas do cliente (ativas, canceladas, expiradas, etc.)
|
503 |
+
subscriptions = await async_stripe_request(
|
504 |
+
stripe.Subscription.list,
|
505 |
customer=user_stripe_id,
|
506 |
expand=["data.items"]
|
507 |
)
|
508 |
|
509 |
logger.info(f"Stripe response data: {subscriptions}")
|
510 |
|
511 |
+
if not subscriptions or not subscriptions["data"]:
|
512 |
# Se não houver assinaturas para o cliente, desativa as assinaturas associadas ao estilista no banco de dados
|
513 |
logger.info(f"No active subscription found for user {user_id}. Deactivating all subscriptions for stylist {data.stylist_id}.")
|
514 |
|
515 |
# 🔹 Buscar todas as assinaturas do estilista no banco de dados para este cliente
|
516 |
+
response_subscriptions = await async_request(
|
517 |
f"{SUPABASE_URL}/rest/v1/Subscriptions?customer_id=eq.{user_id}&stylist_id=eq.{data.stylist_id}",
|
518 |
+
SUPABASE_HEADERS
|
519 |
)
|
520 |
if response_subscriptions.status_code == 200:
|
521 |
subscriptions_data = response_subscriptions.json()
|
522 |
+
await asyncio.gather(
|
523 |
+
*(update_subscription_status(sub['id'], False) for sub in subscriptions_data)
|
524 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
525 |
else:
|
526 |
logger.error(f"❌ Failed to fetch subscriptions from Supabase for stylist {data.stylist_id} and user {user_id}.")
|
527 |
|
|
|
561 |
"canceled_date": canceled_at_date
|
562 |
}
|
563 |
|
564 |
+
await async_request(
|
565 |
f"{SUPABASE_URL}/rest/v1/Subscriptions",
|
566 |
+
SUPABASE_HEADERS,
|
567 |
+
json=subscription_data,
|
568 |
+
method='POST'
|
569 |
)
|
570 |
|
|
|
|
|
|
|
|
|
|
|
571 |
# Retorna informações sobre a assinatura sincronizada
|
572 |
return {
|
573 |
"status": status,
|
|
|
583 |
logger.info(f"No active subscription found for stylist {data.stylist_id}. Deactivating all subscriptions for this stylist.")
|
584 |
|
585 |
# 🔹 Buscar todas as assinaturas do estilista no banco de dados
|
586 |
+
response_subscriptions = await async_request(
|
587 |
f"{SUPABASE_URL}/rest/v1/Subscriptions?stylist_id=eq.{data.stylist_id}",
|
588 |
+
SUPABASE_HEADERS
|
589 |
)
|
590 |
if response_subscriptions.status_code == 200:
|
591 |
subscriptions_data = response_subscriptions.json()
|
592 |
+
await asyncio.gather(
|
593 |
+
*(update_subscription_status(sub['id'], False) for sub in subscriptions_data)
|
594 |
+
)
|
595 |
+
else:
|
596 |
+
logger.error(f"❌ Failed to fetch subscriptions from Supabase for stylist {data.stylist_id}.")
|
597 |
+
|
598 |
+
return {"status": "inactive", "message": "No active subscription found for stylist."}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
599 |
|
600 |
except stripe.error.StripeError as e:
|
601 |
logger.error(f"Stripe error: {str(e)}")
|
602 |
raise HTTPException(status_code=500, detail=f"Stripe error: {str(e)}")
|
603 |
except Exception as e:
|
604 |
logger.error(f"Error checking subscription: {str(e)}")
|
605 |
+
raise HTTPException(status_code=500, detail="Error checking subscription.")
|
606 |
+
|
607 |
+
|
608 |
+
# Função assíncrona para fazer requisições de rede
|
609 |
+
async def async_request(url, headers, json=None, method='GET'):
|
610 |
+
method_func = requests.post if method == 'POST' else requests.get
|
611 |
+
response = method_func(url, headers=headers, json=json)
|
612 |
+
return response
|
613 |
+
|
614 |
+
# Função assíncrona para chamar a Stripe API
|
615 |
+
async def async_stripe_request(func, **kwargs):
|
616 |
+
loop = asyncio.get_event_loop()
|
617 |
+
response = await loop.run_in_executor(None, lambda: func(**kwargs))
|
618 |
+
return response
|
619 |
+
|
620 |
+
# Função assíncrona para atualizar o status de uma assinatura
|
621 |
+
async def update_subscription_status(subscription_id, status):
|
622 |
+
update_data = {
|
623 |
+
"active": status
|
624 |
+
}
|
625 |
+
subscription_url = f"{SUPABASE_URL}/rest/v1/Subscriptions?id=eq.{subscription_id}"
|
626 |
+
update_response = await async_request(
|
627 |
+
subscription_url,
|
628 |
+
SUPABASE_HEADERS,
|
629 |
+
json=update_data,
|
630 |
+
method='PATCH'
|
631 |
+
)
|
632 |
+
if update_response.status_code == 200:
|
633 |
+
logger.info(f"✅ Subscription {subscription_id} deactivated successfully.")
|
634 |
+
else:
|
635 |
+
logger.error(f"❌ Failed to deactivate subscription {subscription_id}.")
|