File size: 7,554 Bytes
efae096
 
 
 
d6be9e0
efae096
4835bd1
d6be9e0
4835bd1
efae096
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d6be9e0
4835bd1
d6be9e0
 
4835bd1
d6be9e0
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4835bd1
 
 
 
 
 
 
 
 
 
 
 
d6be9e0
 
 
 
4835bd1
d6be9e0
 
 
 
4835bd1
d6be9e0
 
 
4835bd1
 
 
 
d6be9e0
 
 
4835bd1
3c6bfef
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
a1ca4b8
 
efae096
a1ca4b8
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4835bd1
d4d3d48
4835bd1
3c6bfef
 
 
d6be9e0
d4d3d48
 
3c6bfef
 
 
d6be9e0
 
4835bd1
 
 
3c6bfef
 
 
d6be9e0
4835bd1
a1ca4b8
 
 
efae096
a1ca4b8
 
efae096
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
import os
import stripe
import requests
import logging
import pytz
from fastapi import APIRouter, HTTPException, Header
from datetime import datetime, timedelta
from dateutil.relativedelta import relativedelta
from typing import List, Dict, Any

router = APIRouter()

# Configuração das chaves do Stripe e Supabase
stripe.api_key = os.getenv("STRIPE_KEY")
stripe.api_version = "2023-10-16"
SUPABASE_URL = "https://ussxqnifefkgkaumjann.supabase.co"
SUPABASE_KEY = os.getenv("SUPA_KEY")

if not stripe.api_key or not SUPABASE_KEY:
    raise ValueError("❌ STRIPE_KEY ou SUPA_KEY não foram definidos no ambiente!")

SUPABASE_HEADERS = {
    "apikey": SUPABASE_KEY,
    "Authorization": f"Bearer {SUPABASE_KEY}",
    "Content-Type": "application/json"
}

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

def verify_token(user_token: str) -> str:
    """
    Valida o token JWT no Supabase e retorna o user_id se for válido.
    """
    headers = {
        "Authorization": f"Bearer {user_token}",
        "apikey": SUPABASE_KEY,
        "Content-Type": "application/json"
    }

    response = requests.get(f"{SUPABASE_URL}/auth/v1/user", headers=headers)

    if response.status_code == 200:
        user_data = response.json()
        user_id = user_data.get("id")
        if not user_id:
            raise HTTPException(status_code=400, detail="Invalid token: User ID not found")
        return user_id
    else:
        raise HTTPException(status_code=401, detail="Invalid or expired token")

def get_monthly_revenue(account_id: str) -> List[Dict[str, Any]]:
    """
    Busca os valores recebidos nos últimos 6 meses para o account_id.
    Retorna uma lista com número do mês, nome do mês, indicador se é o mês atual e valor.
    """
    # Obter data atual no fuso horário de Nova York
    ny_timezone = pytz.timezone('America/New_York')
    now_ny = datetime.now(ny_timezone)
    current_month = now_ny.month
    current_year = now_ny.year
    
    # Preparar dicionário com os últimos 6 meses (incluindo o atual)
    monthly_data = {}
    
    # Criar entradas para os últimos 6 meses, mesmo sem dados
    for i in range(6):
        # Calcular o mês e ano para i meses atrás
        target_date = now_ny - relativedelta(months=i)
        month_num = target_date.month
        month_name = target_date.strftime('%b')  # Formato abreviado do mês (Jan, Feb, etc)
        year = target_date.year
        
        # Chave composta para garantir unicidade (ano-mês)
        month_key = f"{year}-{month_num}"
        
        # Verificar se é o mês atual
        is_current = (month_num == current_month and year == current_year)
        
        monthly_data[month_key] = {
            "month": month_num,
            "name": month_name,
            "current": is_current,
            "amount": 0
        }
    
    # Calcular o timestamp para 6 meses atrás
    start_date = now_ny - relativedelta(months=6)
    start_timestamp = int(start_date.timestamp())
    
    # Buscar transferências para a conta
    try:
        transfers = stripe.Transfer.list(
            destination=account_id,
            created={"gte": start_timestamp},
            limit=100  # Limitando a 100 transferências mais recentes
        )
        
        # Processar as transferências
        for transfer in transfers.data:
            transfer_date = datetime.fromtimestamp(transfer.created, ny_timezone)
            month_num = transfer_date.month
            year = transfer_date.year
            month_key = f"{year}-{month_num}"
            
            # Verificar se o mês está dentro dos últimos 6 meses
            if month_key in monthly_data:
                # Adicionar o valor da transferência (em centavos)
                monthly_data[month_key]["amount"] += transfer.amount
        
        # Converter para lista e ordenar por data (mais antigo primeiro)
        result = list(monthly_data.values())
        result.sort(key=lambda x: (current_month - x["month"]) % 12)
        
        return result
        
    except Exception as e:
        logger.error(f"❌ Error getting monthly revenue: {str(e)}")
        # Retornar os meses mesmo sem transferências
        return list(monthly_data.values())

def get_account_balance(account_id: str) -> Dict[str, Any]:
    """
    Busca o saldo disponível e pendente da conta Stripe.
    """
    try:
        balance = stripe.Balance.retrieve(stripe_account=account_id)
        
        # Inicializar valores
        available_balance = 0
        pending_balance = 0
        currency = "BRL"  # Default para BRL
        
        # Calcular saldo disponível
        for balance_item in balance.available:
            if balance_item.currency.upper() == "BRL":
                available_balance = balance_item.amount
                currency = "BRL"
                break
                
        # Calcular saldo pendente
        for balance_item in balance.pending:
            if balance_item.currency.upper() == "BRL":
                pending_balance = balance_item.amount
                break
                
        return {
            "available_balance": available_balance,
            "pending_balance": pending_balance,
            "currency": currency
        }
        
    except Exception as e:
        logger.error(f"❌ Error getting account balance: {str(e)}")
        return {
            "available_balance": 0,
            "pending_balance": 0,
            "currency": "BRL"
        }

@router.get("/dashboard")
def get_dashboard(user_token: str = Header(None, alias="User-key")):
    try:
        if not user_token:
            raise HTTPException(status_code=401, detail="Missing User-key header")
        
        # Validar o token e obter user_id
        user_id = verify_token(user_token)
        logger.info(f"🔹 User verified. user_id: {user_id}")

        # Buscar stripe_id do usuário no Supabase
        user_data_url = f"{SUPABASE_URL}/rest/v1/User?id=eq.{user_id}"
        response = requests.get(
            user_data_url, 
            headers={
                "Authorization": f"Bearer {user_token}",
                "apikey": SUPABASE_KEY,
                "Content-Type": "application/json"
            }
        )
        
        if response.status_code != 200 or not response.json():
            raise HTTPException(status_code=404, detail="User not found")
            
        user_data = response.json()[0]
        stripe_id = user_data.get("stripe_id")
        
        if not stripe_id:
            return {
                "stripe_id": None,
                "available_balance": 0,
                "pending_balance": 0,
                "currency": "BRL",
                "monthly_revenue": []
            }
        
        # Buscar saldo da conta
        balance_info = get_account_balance(stripe_id)
        
        # Buscar valores recebidos nos últimos 6 meses
        monthly_revenue = get_monthly_revenue(stripe_id)
        
        return {
            "stripe_id": stripe_id,
            "available_balance": balance_info["available_balance"],
            "pending_balance": balance_info["pending_balance"],
            "currency": balance_info["currency"],
            "monthly_revenue": monthly_revenue
        }

    except HTTPException as http_err:
        raise http_err
    except Exception as e:
        error_message = str(e) if str(e) else "An unknown error occurred"
        logger.error(f"❌ Error: {error_message}")
        raise HTTPException(status_code=500, detail=error_message)