Arthur-Attili commited on
Commit
08ba218
·
verified ·
1 Parent(s): 67d28c6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +130 -42
app.py CHANGED
@@ -6,65 +6,59 @@ Original file is located at
6
 
7
  # app.py
8
  import pandas as pd
 
 
9
  import itertools
10
  from collections import defaultdict
11
  import gradio as gr
12
- from supabase import create_client, Client
13
- import os
14
 
15
- # 🔧 CONFIGURAÇÕES GLOBAIS - SUPABASE
16
- SUPABASE_URL = os.environ.get("SUPABASE_URL")
17
- SUPABASE_KEY = os.environ.get("SUPABASE_KEY")
18
- supabase: Client = create_client(SUPABASE_URL, SUPABASE_KEY)
19
 
20
  # Variável global para armazenar o DataFrame
21
  df = None
22
 
23
  def carregar_planilha():
24
- """Carrega e prepara os dados do Supabase para análise."""
25
  global df
26
  try:
27
- print("⏳ Carregando dados do Supabase...")
28
-
29
- # Busca todos os dados da tabela cotas
30
- response = supabase.table("cotas").select("*").execute()
31
-
32
- # Converte para DataFrame
33
- df = pd.DataFrame(response.data)
34
-
35
- if df.empty:
36
- raise ValueError("Nenhum dado encontrado no Supabase")
37
 
38
  # Padroniza nomes das colunas
39
  df.columns = df.columns.str.strip().str.lower().str.replace(" ", "_")
40
 
41
- # Converte colunas numéricas - USANDO OS NOMES CORRETOS DO SEU SUPABASE
42
- colunas_numericas = ['valor_credito', 'entrada', 'valor_parcela', 'saldo', 'parcelas']
43
  for coluna in colunas_numericas:
44
  if coluna in df.columns:
45
  df[coluna] = pd.to_numeric(df[coluna], errors='coerce').fillna(0)
46
 
47
  # Verifica colunas essenciais
48
- if 'categoria' not in df.columns or 'administradora_id' not in df.columns:
49
  raise ValueError("Colunas essenciais não encontradas")
50
 
51
  # Remove duplicatas
52
  df.drop_duplicates(inplace=True)
53
 
54
- print("✅ Dados carregados com sucesso do Supabase")
55
- print(f"📊 Colunas disponíveis: {list(df.columns)}")
56
  return True
57
 
58
  except Exception as e:
59
- print(f"❌ Erro ao carregar dados do Supabase: {str(e)}")
60
  return False
61
 
62
  def agrupar_por_administradora(dataframe):
63
  """Agrupa cotas por administradora."""
64
  grupos = defaultdict(list)
65
  for _, row in dataframe.iterrows():
66
- # CORRIGIDO: usando administradora_id consistentemente
67
- grupos[row['administradora_id']].append(row.to_dict())
68
  return grupos
69
 
70
  def buscar_combinacoes(credito_desejado, entrada_desejada, parcela_desejada, administradoras=None):
@@ -73,18 +67,15 @@ def buscar_combinacoes(credito_desejado, entrada_desejada, parcela_desejada, adm
73
  if df is None:
74
  # Tenta carregar se ainda não foi carregado
75
  if not carregar_planilha():
76
- return "❌ Erro: Dados não carregados. Por favor, tente novamente."
77
 
78
  # Filtra por tipo de bem e administradoras
79
- df_filtrado = df[df['categoria'].str.lower() == 'imovel']
80
-
81
  if administradoras:
82
  # Certifica-se de que administradoras é uma lista (Gradio retorna tupla)
83
  if isinstance(administradoras, tuple):
84
  administradoras = list(administradoras)
85
-
86
- # CORRIGIDO: usando administradora_id consistentemente
87
- df_filtrado = df_filtrado[df_filtrado['administradora_id'].isin(administradoras)]
88
 
89
  if df_filtrado.empty:
90
  return "🚫 Nenhuma cota encontrada com os filtros aplicados. Tente ajustar os parâmetros."
@@ -101,15 +92,15 @@ def buscar_combinacoes(credito_desejado, entrada_desejada, parcela_desejada, adm
101
  for r in range(1, min(3, len(cotas)) + 1): # Máximo 3 cotas por combinação
102
  for combinacao in itertools.combinations(cotas, r):
103
  total_credito = sum(c['valor_credito'] for c in combinacao)
104
- total_entrada_base = sum(c['entrada'] for c in combinacao) # CORRIGIDO: 'entrada'
105
  total_entrada = total_entrada_base + (total_credito * 0.085) # aplica os 8,5% sobre o crédito
106
- total_parcelas = sum(c['valor_parcela'] for c in combinacao) # CORRIGIDO: 'valor_parcela'
107
 
108
  if (credito_min <= total_credito <= credito_max and
109
  entrada_min <= total_entrada <= entrada_max and
110
  parcela_min <= total_parcelas <= parcela_max):
111
 
112
- total_saldo = sum(c['saldo'] for c in combinacao) # CORRIGIDO: 'saldo'
113
  valor_final = round(total_entrada + total_saldo, 2)
114
  diferenca = abs(valor_final - total_credito) # Diferença do valor final pelo crédito (para ordenação)
115
 
@@ -132,11 +123,11 @@ def formatar_resultados(resultados):
132
  for idx, (adm, combinacao, _) in enumerate(resultados[:15], 1):
133
  codigos = [str(c.get('codigo', 'N/A')) for c in combinacao]
134
  total_credito = sum(c['valor_credito'] for c in combinacao)
135
- total_entrada_base = sum(c['entrada'] for c in combinacao) # CORRIGIDO: 'entrada'
136
  total_entrada = total_entrada_base + (total_credito * 0.085)
137
- total_saldo = sum(c['saldo'] for c in combinacao) # CORRIGIDO: 'saldo'
138
- total_parcelas = sum(c['valor_parcela'] for c in combinacao) # CORRIGIDO: 'valor_parcela'
139
- maior_prazo = max(int(c.get('parcelas', 0)) for c in combinacao) # CORRIGIDO: 'parcelas'
140
 
141
  valor_final = round(total_entrada + total_saldo, 2)
142
  credito_real = round(total_credito - total_entrada, 2)
@@ -161,7 +152,7 @@ def formatar_resultados(resultados):
161
  """
162
  return resposta
163
 
164
- # Carrega os dados uma vez quando o aplicativo inicia
165
  carregar_planilha()
166
 
167
  def ajustar_e_buscar(credito_desejado, entrada_desejada, parcela_desejada, administradoras):
@@ -171,11 +162,108 @@ def ajustar_e_buscar(credito_desejado, entrada_desejada, parcela_desejada, admin
171
  # Prepara a lista de administradoras para o Gradio
172
  def get_administradoras_options():
173
  if df is not None:
174
- # CORRIGIDO: usando administradora_id consistentemente
175
- adm_list = df[df['categoria'].str.lower() == 'imovel']['administradora_id'].unique()
176
  return sorted(adm_list)
177
  return []
178
 
179
  # Criando a interface Gradio
180
  with gr.Blocks(title="Sistema de Busca de Consórcio Imóvel") as demo:
181
- # ... (o restante do código da interface permanece igual)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
 
7
  # app.py
8
  import pandas as pd
9
+ import requests
10
+ import io
11
  import itertools
12
  from collections import defaultdict
13
  import gradio as gr
14
+ import time
 
15
 
16
+ # 🔧 CONFIGURAÇÕES GLOBAIS
17
+ # Certifique-se de que este FILE_ID esteja acessível publicamente ou para "Qualquer pessoa com o link"
18
+ FILE_ID = "1XvNz7DlWioT64uNdcfBSL8Ui2nRSi9gT"
19
+ URL = f"https://drive.google.com/uc?export=download&id={FILE_ID}"
20
 
21
  # Variável global para armazenar o DataFrame
22
  df = None
23
 
24
  def carregar_planilha():
25
+ """Carrega e prepara a planilha para análise."""
26
  global df
27
  try:
28
+ print("⏳ Carregando planilha...")
29
+ response = requests.get(URL)
30
+ response.raise_for_status()
31
+ data = io.BytesIO(response.content)
32
+ df = pd.read_excel(data)
 
 
 
 
 
33
 
34
  # Padroniza nomes das colunas
35
  df.columns = df.columns.str.strip().str.lower().str.replace(" ", "_")
36
 
37
+ # Converte colunas numéricas
38
+ colunas_numericas = ['valor_credito', 'valor_entrada', 'valor_parcela', 'saldo_devedor', 'qtd_parcelas']
39
  for coluna in colunas_numericas:
40
  if coluna in df.columns:
41
  df[coluna] = pd.to_numeric(df[coluna], errors='coerce').fillna(0)
42
 
43
  # Verifica colunas essenciais
44
+ if 'tipo_do_bem' not in df.columns or 'administradora' not in df.columns:
45
  raise ValueError("Colunas essenciais não encontradas")
46
 
47
  # Remove duplicatas
48
  df.drop_duplicates(inplace=True)
49
 
50
+ print("✅ Planilha carregada com sucesso")
 
51
  return True
52
 
53
  except Exception as e:
54
+ print(f"❌ Erro ao carregar planilha: {str(e)}")
55
  return False
56
 
57
  def agrupar_por_administradora(dataframe):
58
  """Agrupa cotas por administradora."""
59
  grupos = defaultdict(list)
60
  for _, row in dataframe.iterrows():
61
+ grupos[row['administradora']].append(row.to_dict())
 
62
  return grupos
63
 
64
  def buscar_combinacoes(credito_desejado, entrada_desejada, parcela_desejada, administradoras=None):
 
67
  if df is None:
68
  # Tenta carregar se ainda não foi carregado
69
  if not carregar_planilha():
70
+ return "❌ Erro: Planilha não carregada. Por favor, tente novamente."
71
 
72
  # Filtra por tipo de bem e administradoras
73
+ df_filtrado = df[df['tipo_do_bem'].str.lower() == 'imovel']
 
74
  if administradoras:
75
  # Certifica-se de que administradoras é uma lista (Gradio retorna tupla)
76
  if isinstance(administradoras, tuple):
77
  administradoras = list(administradoras)
78
+ df_filtrado = df_filtrado[df_filtrado['administradora'].isin(administradoras)]
 
 
79
 
80
  if df_filtrado.empty:
81
  return "🚫 Nenhuma cota encontrada com os filtros aplicados. Tente ajustar os parâmetros."
 
92
  for r in range(1, min(3, len(cotas)) + 1): # Máximo 3 cotas por combinação
93
  for combinacao in itertools.combinations(cotas, r):
94
  total_credito = sum(c['valor_credito'] for c in combinacao)
95
+ total_entrada_base = sum(c['valor_entrada'] for c in combinacao)
96
  total_entrada = total_entrada_base + (total_credito * 0.085) # aplica os 8,5% sobre o crédito
97
+ total_parcelas = sum(c['valor_parcela'] for c in combinacao)
98
 
99
  if (credito_min <= total_credito <= credito_max and
100
  entrada_min <= total_entrada <= entrada_max and
101
  parcela_min <= total_parcelas <= parcela_max):
102
 
103
+ total_saldo = sum(c['saldo_devedor'] for c in combinacao)
104
  valor_final = round(total_entrada + total_saldo, 2)
105
  diferenca = abs(valor_final - total_credito) # Diferença do valor final pelo crédito (para ordenação)
106
 
 
123
  for idx, (adm, combinacao, _) in enumerate(resultados[:15], 1):
124
  codigos = [str(c.get('codigo', 'N/A')) for c in combinacao]
125
  total_credito = sum(c['valor_credito'] for c in combinacao)
126
+ total_entrada_base = sum(c['valor_entrada'] for c in combinacao)
127
  total_entrada = total_entrada_base + (total_credito * 0.085)
128
+ total_saldo = sum(c['saldo_devedor'] for c in combinacao)
129
+ total_parcelas = sum(c['valor_parcela'] for c in combinacao)
130
+ maior_prazo = max(int(c.get('qtd_parcelas', 0)) for c in combinacao)
131
 
132
  valor_final = round(total_entrada + total_saldo, 2)
133
  credito_real = round(total_credito - total_entrada, 2)
 
152
  """
153
  return resposta
154
 
155
+ # Carrega a planilha uma vez quando o aplicativo inicia
156
  carregar_planilha()
157
 
158
  def ajustar_e_buscar(credito_desejado, entrada_desejada, parcela_desejada, administradoras):
 
162
  # Prepara a lista de administradoras para o Gradio
163
  def get_administradoras_options():
164
  if df is not None:
165
+ adm_list = df[df['tipo_do_bem'].str.lower() == 'imovel']['administradora'].unique()
 
166
  return sorted(adm_list)
167
  return []
168
 
169
  # Criando a interface Gradio
170
  with gr.Blocks(title="Sistema de Busca de Consórcio Imóvel") as demo:
171
+ gr.HTML("""
172
+ <link href="https://fonts.googleapis.com/css2?family=Poppins&display=swap" rel="stylesheet">
173
+ <style>
174
+ * {
175
+ font-family: 'Poppins', sans-serif !important;
176
+ }
177
+
178
+ body {
179
+ background-color: #ff8f00 !important;
180
+ color: black !important;
181
+ }
182
+
183
+ /* Inputs Numéricos: Crédito, Entrada, Parcela */
184
+ input[type="number"] {
185
+ background-color: white !important;
186
+ border: 2px solid #000 !important;
187
+ border-radius: 12px !important;
188
+ color: black !important;
189
+ padding: 10px !important;
190
+ font-weight: 500;
191
+ }
192
+
193
+ /* Inputs de texto e áreas de texto (como a saída e código) */
194
+ input[type="text"], textarea {
195
+ background-color: white !important;
196
+ border: 2px solid black !important;
197
+ border-radius: 12px !important;
198
+ color: black !important;
199
+ padding: 10px !important;
200
+ }
201
+
202
+ input::placeholder, textarea::placeholder {
203
+ color: #333 !important;
204
+ opacity: 0.7;
205
+ }
206
+
207
+ .gr-checkbox label {
208
+ display: flex;
209
+ align-items: center;
210
+ gap: 8px;
211
+ font-weight: 600;
212
+ }
213
+
214
+ input[type="checkbox"] {
215
+ accent-color: black !important;
216
+ width: 18px;
217
+ height: 18px;
218
+ }
219
+
220
+ .gr-button {
221
+ font-weight: bold;
222
+ border-radius: 10px !important;
223
+ background-color: white !important;
224
+ color: black !important;
225
+ border: 2px solid black !important;
226
+ }
227
+
228
+ .gr-button:hover {
229
+ background-color: #fff3e0 !important;
230
+ color: black !important;
231
+ }
232
+
233
+ label {
234
+ font-weight: 600 !important;
235
+ }
236
+ </style>
237
+ """)
238
+
239
+
240
+ gr.Markdown("# 🏠 Busca de Combinações de Consórcio Imóvel")
241
+ gr.Markdown("Insira os valores desejados para crédito, entrada e parcela, e filtre por administradora.")
242
+
243
+ with gr.Row():
244
+ credito_input = gr.Number(label="Crédito Desejado (R$)", value=300000, step=1000)
245
+ entrada_input = gr.Number(label="Entrada Desejada (R$)", value=30000, step=1000)
246
+ parcela_input = gr.Number(label="Parcela Desejada (R$)", value=1500, step=100)
247
+
248
+ administradoras_multiselect = gr.CheckboxGroup(
249
+ label="Filtrar por Administradoras",
250
+ choices=get_administradoras_options(),
251
+ value=get_administradoras_options() # Seleciona todas por padrão
252
+ )
253
+
254
+ submit_btn = gr.Button("🔍 Buscar Combinações", variant="primary")
255
+
256
+ output_text = gr.Textbox(label="Resultados da Busca", lines=20, max_lines=40, interactive=False, placeholder="Os resultados aparecerão aqui...")
257
+
258
+ submit_btn.click(
259
+ fn=ajustar_e_buscar,
260
+ inputs=[credito_input, entrada_input, parcela_input, administradoras_multiselect],
261
+ outputs=output_text
262
+ )
263
+
264
+ gr.Markdown("---")
265
+ gr.Markdown("Desenvolvido para auxiliar na busca por cotas de consórcio ideais.")
266
+
267
+ # Inicia o aplicativo Gradio
268
+ if __name__ == "__main__":
269
+ demo.launch() # Você não precisa disso no Colab, mas sim no arquivo que você fará o deploy