Arthur-Attili commited on
Commit
04fc756
·
verified ·
1 Parent(s): ce87491

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +13 -110
app.py CHANGED
@@ -1,108 +1,75 @@
1
- # app.py - VERSÃO COM MARGEM ABSOLUTA FIXA + CORS CORRIGIDO
2
  import pandas as pd
3
  import requests
4
  import io
5
  import itertools
6
  from collections import defaultdict
7
  import gradio as gr
8
-
9
- # ========== NOVO: import para CORS ==========
10
  from fastapi.middleware.cors import CORSMiddleware
11
 
12
  # 🔧 CONFIGURAÇÕES GLOBAIS
13
  FILE_ID = "1XvNz7DlWioT64uNdcfBSL8Ui2nRSi9gT"
14
  URL = f"https://drive.google.com/uc?export=download&id={FILE_ID}"
15
 
16
- # Variáveis globais para armazenamento
17
  df = None
18
  df_imovel = None
19
  grupos_imovel = None
20
  planilha_carregada = False
21
 
22
-
23
  def carregar_planilha():
24
- """Carrega e prepara a planilha para análise."""
25
  global df, df_imovel, grupos_imovel, planilha_carregada
26
-
27
  if planilha_carregada:
28
  return True
29
-
30
  try:
31
  print("⏳ Carregando planilha...")
32
  response = requests.get(URL)
33
  response.raise_for_status()
34
  data = io.BytesIO(response.content)
35
  df = pd.read_excel(data)
36
-
37
- # Padroniza nomes das colunas
38
  df.columns = df.columns.str.strip().str.lower().str.replace(" ", "_")
39
-
40
- # Colunas numéricas
41
  colunas_numericas = ['valor_credito', 'valor_entrada', 'valor_parcela', 'saldo_devedor', 'qtd_parcelas']
42
  for coluna in colunas_numericas:
43
  if coluna in df.columns:
44
  df[coluna] = pd.to_numeric(df[coluna], errors='coerce').fillna(0)
45
-
46
- # Verifica colunas essenciais
47
  if 'tipo_do_bem' not in df.columns or 'administradora' not in df.columns:
48
  raise ValueError("Colunas essenciais não encontradas")
49
-
50
  df.drop_duplicates(inplace=True)
51
-
52
- # Pré‑processa imóvel
53
  df_imovel = df[df['tipo_do_bem'].str.lower() == 'imovel'].copy()
54
  grupos_imovel = agrupar_por_administradora(df_imovel)
55
-
56
  planilha_carregada = True
57
- print("✅ Planilha carregada e pré-processada com sucesso")
58
- print(f"✅ Total de cotas de imóvel: {len(df_imovel)}")
59
- print(f"✅ Administradoras disponíveis: {list(grupos_imovel.keys())}")
60
  return True
61
-
62
  except Exception as e:
63
- print(f"❌ Erro ao carregar planilha: {str(e)}")
64
  return False
65
 
66
-
67
  def agrupar_por_administradora(dataframe):
68
- """Agrupa cotas por administradora."""
69
  grupos = defaultdict(list)
70
  for _, row in dataframe.iterrows():
71
  grupos[row['administradora']].append(row.to_dict())
72
  return grupos
73
 
74
-
75
  def formatar_moeda(valor):
76
  return f"R$ {valor:,.2f}".replace(",", "v").replace(".", ",").replace("v", ".")
77
 
78
-
79
  def calcular_tempo_parcelas(combinacao):
80
- """Calcula o tempo de parcelas baseado nas cotas da combinação."""
81
  if not combinacao:
82
  return ""
83
-
84
  try:
85
  cotas_ordenadas = sorted(combinacao, key=lambda x: int(x.get('qtd_parcelas', 0)))
86
  prazos = sorted(set(int(c.get('qtd_parcelas', 0)) for c in combinacao))
87
-
88
  if not prazos or prazos[0] <= 0:
89
  return ""
90
-
91
  resultado = []
92
  prazo_anterior = 0
93
-
94
  for prazo_atual in prazos:
95
  cotas_ativas = [c for c in cotas_ordenadas if int(c.get('qtd_parcelas', 0)) >= prazo_anterior + 1]
96
  valor_parcela_total = sum(c.get('valor_parcela', 0) for c in cotas_ativas)
97
-
98
  inicio = prazo_anterior + 1
99
  fim = prazo_atual
100
-
101
  if inicio <= fim and valor_parcela_total > 0:
102
  resultado.append(f"{inicio}x à {fim}x: {formatar_moeda(valor_parcela_total)}/mês")
103
-
104
  prazo_anterior = prazo_atual
105
-
106
  if prazos and prazo_anterior < max(prazos):
107
  cotas_ativas_finais = [c for c in cotas_ordenadas if int(c.get('qtd_parcelas', 0)) > prazo_anterior]
108
  if cotas_ativas_finais:
@@ -111,124 +78,78 @@ def calcular_tempo_parcelas(combinacao):
111
  fim_final = max(prazos)
112
  if valor_parcela_final > 0:
113
  resultado.append(f"{inicio_final}x à {fim_final}x: {formatar_moeda(valor_parcela_final)}/mês")
114
-
115
  return "\\n".join(resultado) if resultado else ""
116
-
117
  except Exception as e:
118
- print(f"❌ Erro ao calcular tempo de parcelas: {str(e)}")
119
  return ""
120
 
121
-
122
  def definir_margens_absolutas(credito_desejado, entrada_desejada, parcela_desejada):
123
- """Define margens fixas em R$ para crédito, entrada e parcela."""
124
  margem_credito = 40_000
125
  margem_entrada = 10_000
126
  margem_parcela = 1_000
127
-
128
  credito_min = max(0, credito_desejado - margem_credito)
129
  credito_max = credito_desejado + margem_credito
130
-
131
  entrada_min = max(0, entrada_desejada - margem_entrada)
132
  entrada_max = entrada_desejada + margem_entrada
133
-
134
  parcela_min = max(0, parcela_desejada - margem_parcela)
135
  parcela_max = parcela_desejada + margem_parcela
136
-
137
  return credito_min, credito_max, entrada_min, entrada_max, parcela_min, parcela_max
138
 
139
-
140
  def filtrar_cotas_por_faixa(cotas, credito_min, credito_max):
141
- """Filtra cotas que pelo menos têm chance de entrar na faixa de crédito."""
142
  return [c for c in cotas if c['valor_credito'] < credito_max * 2]
143
 
144
-
145
  def buscar_combinacoes_otimizado(credito_desejado, entrada_desejada, parcela_desejada, administradoras=None, max_combinacoes=15):
146
- """Busca combinações de cotas dentro de margens fixas absolutas."""
147
  global df_imovel, grupos_imovel
148
-
149
  if not planilha_carregada:
150
  if not carregar_planilha():
151
- return "❌ Erro: Planilha não carregada. Por favor, tente novamente."
152
-
153
- # Filtra administradoras
154
  if administradoras and len(administradoras) > 0:
155
  grupos_filtrados = {adm: cotas for adm, cotas in grupos_imovel.items() if adm in administradoras}
156
  else:
157
  grupos_filtrados = grupos_imovel
158
-
159
  if not grupos_filtrados:
160
- return "🚫 Nenhuma cota encontrada com os filtros aplicados. Tente ajustar os parâmetros."
161
-
162
- print(f"🔍 Total de administradoras no filtro: {len(grupos_filtrados)}")
163
-
164
- # Usa margens fixas em R$
165
  credito_min, credito_max, entrada_min, entrada_max, parcela_min, parcela_max = definir_margens_absolutas(
166
  credito_desejado, entrada_desejada, parcela_desejada
167
  )
168
-
169
- print(f"💰 Valores desejados: Crédito: R$ {credito_desejado:,.2f}, Entrada: R$ {entrada_desejada:,.2f}, Parcela: R$ {parcela_desejada:,.2f}")
170
- print(f"🔍 Margem de crédito: de R$ {credito_min:,.2f} até R$ {credito_max:,.2f}")
171
-
172
- # Limites de busca
173
  max_cotas_combinacao = 15
174
  max_combinacoes_por_adm = 4000
175
-
176
  resultados = []
177
  total_combinacoes_testadas = 0
178
-
179
  for adm, cotas in grupos_filtrados.items():
180
- print(f"🔍 Analisando administradora: {adm} ({len(cotas)} cotas)")
181
-
182
  cotas_filtradas = filtrar_cotas_por_faixa(cotas, credito_min, credito_max)
183
-
184
  for r in range(1, min(max_cotas_combinacao + 1, len(cotas_filtradas) + 1)):
185
  combinacoes_geradas = 0
186
  for combinacao in itertools.combinations(cotas_filtradas, r):
187
  if combinacoes_geradas >= max_combinacoes_por_adm:
188
  break
189
-
190
  total_combinacoes_testadas += 1
191
  combinacoes_geradas += 1
192
-
193
  total_credito = sum(c['valor_credito'] for c in combinacao)
194
  total_entrada_base = sum(c['valor_entrada'] for c in combinacao)
195
  total_entrada = total_entrada_base + (total_credito * 0.085)
196
  total_parcelas = sum(c['valor_parcela'] for c in combinacao)
197
-
198
  if (credito_min <= total_credito <= credito_max and
199
  entrada_min <= total_entrada <= entrada_max and
200
  parcela_min <= total_parcelas <= parcela_max):
201
-
202
  total_saldo = sum(c['saldo_devedor'] for c in combinacao)
203
  valor_final = round(total_entrada + total_saldo, 2)
204
  diferenca = abs(valor_final - total_credito)
205
-
206
  resultados.append((adm, combinacao, diferenca))
207
-
208
  if len(resultados) >= max_combinacoes * 2:
209
  break
210
-
211
  if len(resultados) >= max_combinacoes * 2:
212
  break
213
-
214
  if len(resultados) >= max_combinacoes * 2:
215
  break
216
-
217
- print(f"🔍 Total de combinações testadas: {total_combinacoes_testadas}")
218
- print(f"🔍 Combinações válidas encontradas: {len(resultados)}")
219
-
220
  if not resultados:
221
- return "🚫 Nenhuma combinação adequada encontrada com os parâmetros fornecidos."
222
-
223
  resultados.sort(key=lambda x: x[2])
224
  return formatar_resultados(resultados[:max_combinacoes])
225
 
226
-
227
  def formatar_resultados(resultados):
228
- """Formata os resultados para exibição incluindo tempo de parcelas."""
229
  if not resultados:
230
- return "🚫 Nenhuma combinação adequada encontrada com os parâmetros fornecidos."
231
-
232
  resposta = ""
233
  for idx, (adm, combinacao, _) in enumerate(resultados, 1):
234
  codigos = [str(c.get('codigo', 'N/A')) for c in combinacao]
@@ -238,15 +159,12 @@ def formatar_resultados(resultados):
238
  total_saldo = sum(c['saldo_devedor'] for c in combinacao)
239
  total_parcelas = sum(c['valor_parcela'] for c in combinacao)
240
  maior_prazo = max(int(c.get('qtd_parcelas', 0)) for c in combinacao)
241
-
242
  valor_final = round(total_entrada + total_saldo, 2)
243
  credito_real = round(total_credito - total_entrada, 2)
244
  taxa_total = total_saldo - credito_real
245
  taxa_percentual = (taxa_total / credito_real) * 100 if credito_real > 0 else 0
246
  taxa_mensal = taxa_percentual / maior_prazo if maior_prazo > 0 else 0
247
-
248
  tempo_parcelas = calcular_tempo_parcelas(combinacao)
249
-
250
  resposta += f"""
251
  --- COMBINAÇÃO {idx} ---
252
  🏢 Administradora: {adm}
@@ -266,11 +184,8 @@ def formatar_resultados(resultados):
266
  """
267
  return resposta
268
 
269
-
270
- # Carrega a planilha uma vez quando o aplicativo inicia
271
  carregar_planilha()
272
 
273
-
274
  def ajustar_e_buscar(credito_desejado, entrada_desejada, parcela_desejada, administradoras):
275
  return buscar_combinacoes_otimizado(
276
  float(credito_desejado or 0),
@@ -280,15 +195,13 @@ def ajustar_e_buscar(credito_desejado, entrada_desejada, parcela_desejada, admin
280
  max_combinacoes=15
281
  )
282
 
283
-
284
  def get_administradoras_options():
285
  if df is not None and planilha_carregada:
286
  adm_list = df[df['tipo_do_bem'].str.lower() == 'imovel']['administradora'].unique()
287
  return sorted(adm_list)
288
  return []
289
 
290
-
291
- # ========== CRIAÇÃO DA INTERFACE GRADIO ==========
292
  with gr.Blocks(title="Sistema de Busca de Consórcio Imóvel") as demo:
293
  gr.HTML("""
294
  <link href="https://fonts.googleapis.com/css2?family=Poppins&display=swap" rel="stylesheet">
@@ -312,49 +225,39 @@ with gr.Blocks(title="Sistema de Busca de Consórcio Imóvel") as demo:
312
  .gr-button:hover { background-color: #fff3e0 !important; }
313
  </style>
314
  """)
315
-
316
  gr.Markdown("# 🏠 Busca de Combinações de Consórcio Imóvel")
317
  gr.Markdown("Insira os valores desejados para crédito, entrada e parcela, e filtre por administradora.")
318
-
319
  with gr.Row():
320
  credito_input = gr.Number(label="Crédito Desejado (R$)", value=300000, step=1000)
321
  entrada_input = gr.Number(label="Entrada Desejada (R$)", value=30000, step=1000)
322
  parcela_input = gr.Number(label="Parcela Desejada (R$)", value=1500, step=100)
323
-
324
  administradoras_multiselect = gr.CheckboxGroup(
325
  label="Filtrar por Administradoras",
326
  choices=get_administradoras_options(),
327
  value=get_administradoras_options()
328
  )
329
-
330
  submit_btn = gr.Button("🔍 Buscar Combinações", variant="primary")
331
  output_text = gr.Textbox(label="Resultados da Busca", lines=20, max_lines=40, interactive=False, placeholder="Os resultados aparecerão aqui...")
332
-
333
  submit_btn.click(
334
  fn=ajustar_e_buscar,
335
  inputs=[credito_input, entrada_input, parcela_input, administradoras_multiselect],
336
- outputs=output_text
 
337
  )
338
-
339
  gr.Markdown("---")
340
  gr.Markdown("Desenvolvido para auxiliar na busca por cotas de consórcio ideais.")
341
 
342
-
343
- # ========== CORREÇÃO DO CORS ==========
344
- # Adiciona middleware para permitir requisições do seu domínio com credenciais
345
  demo.app.add_middleware(
346
  CORSMiddleware,
347
  allow_origins=[
348
  "https://www.maxconconsorcios.com.br",
349
  "https://maxconconsorcios.com.br",
350
- # Para testes, você pode adicionar "http://localhost:7860" se necessário
351
  ],
352
- allow_credentials=True, # ESSENCIAL para resolver o erro de credenciais
353
  allow_methods=["*"],
354
  allow_headers=["*"],
355
  )
356
 
357
-
358
- # ========== INICIALIZAÇÃO ==========
359
  if __name__ == "__main__":
360
  demo.launch()
 
1
+ # app.py - VERSÃO FINAL COM CORS E API_NAME
2
  import pandas as pd
3
  import requests
4
  import io
5
  import itertools
6
  from collections import defaultdict
7
  import gradio as gr
 
 
8
  from fastapi.middleware.cors import CORSMiddleware
9
 
10
  # 🔧 CONFIGURAÇÕES GLOBAIS
11
  FILE_ID = "1XvNz7DlWioT64uNdcfBSL8Ui2nRSi9gT"
12
  URL = f"https://drive.google.com/uc?export=download&id={FILE_ID}"
13
 
 
14
  df = None
15
  df_imovel = None
16
  grupos_imovel = None
17
  planilha_carregada = False
18
 
 
19
  def carregar_planilha():
 
20
  global df, df_imovel, grupos_imovel, planilha_carregada
 
21
  if planilha_carregada:
22
  return True
 
23
  try:
24
  print("⏳ Carregando planilha...")
25
  response = requests.get(URL)
26
  response.raise_for_status()
27
  data = io.BytesIO(response.content)
28
  df = pd.read_excel(data)
 
 
29
  df.columns = df.columns.str.strip().str.lower().str.replace(" ", "_")
 
 
30
  colunas_numericas = ['valor_credito', 'valor_entrada', 'valor_parcela', 'saldo_devedor', 'qtd_parcelas']
31
  for coluna in colunas_numericas:
32
  if coluna in df.columns:
33
  df[coluna] = pd.to_numeric(df[coluna], errors='coerce').fillna(0)
 
 
34
  if 'tipo_do_bem' not in df.columns or 'administradora' not in df.columns:
35
  raise ValueError("Colunas essenciais não encontradas")
 
36
  df.drop_duplicates(inplace=True)
 
 
37
  df_imovel = df[df['tipo_do_bem'].str.lower() == 'imovel'].copy()
38
  grupos_imovel = agrupar_por_administradora(df_imovel)
 
39
  planilha_carregada = True
40
+ print("✅ Planilha carregada")
 
 
41
  return True
 
42
  except Exception as e:
43
+ print(f"❌ Erro: {str(e)}")
44
  return False
45
 
 
46
  def agrupar_por_administradora(dataframe):
 
47
  grupos = defaultdict(list)
48
  for _, row in dataframe.iterrows():
49
  grupos[row['administradora']].append(row.to_dict())
50
  return grupos
51
 
 
52
  def formatar_moeda(valor):
53
  return f"R$ {valor:,.2f}".replace(",", "v").replace(".", ",").replace("v", ".")
54
 
 
55
  def calcular_tempo_parcelas(combinacao):
 
56
  if not combinacao:
57
  return ""
 
58
  try:
59
  cotas_ordenadas = sorted(combinacao, key=lambda x: int(x.get('qtd_parcelas', 0)))
60
  prazos = sorted(set(int(c.get('qtd_parcelas', 0)) for c in combinacao))
 
61
  if not prazos or prazos[0] <= 0:
62
  return ""
 
63
  resultado = []
64
  prazo_anterior = 0
 
65
  for prazo_atual in prazos:
66
  cotas_ativas = [c for c in cotas_ordenadas if int(c.get('qtd_parcelas', 0)) >= prazo_anterior + 1]
67
  valor_parcela_total = sum(c.get('valor_parcela', 0) for c in cotas_ativas)
 
68
  inicio = prazo_anterior + 1
69
  fim = prazo_atual
 
70
  if inicio <= fim and valor_parcela_total > 0:
71
  resultado.append(f"{inicio}x à {fim}x: {formatar_moeda(valor_parcela_total)}/mês")
 
72
  prazo_anterior = prazo_atual
 
73
  if prazos and prazo_anterior < max(prazos):
74
  cotas_ativas_finais = [c for c in cotas_ordenadas if int(c.get('qtd_parcelas', 0)) > prazo_anterior]
75
  if cotas_ativas_finais:
 
78
  fim_final = max(prazos)
79
  if valor_parcela_final > 0:
80
  resultado.append(f"{inicio_final}x à {fim_final}x: {formatar_moeda(valor_parcela_final)}/mês")
 
81
  return "\\n".join(resultado) if resultado else ""
 
82
  except Exception as e:
83
+ print(f"❌ Erro ao calcular tempo: {str(e)}")
84
  return ""
85
 
 
86
  def definir_margens_absolutas(credito_desejado, entrada_desejada, parcela_desejada):
 
87
  margem_credito = 40_000
88
  margem_entrada = 10_000
89
  margem_parcela = 1_000
 
90
  credito_min = max(0, credito_desejado - margem_credito)
91
  credito_max = credito_desejado + margem_credito
 
92
  entrada_min = max(0, entrada_desejada - margem_entrada)
93
  entrada_max = entrada_desejada + margem_entrada
 
94
  parcela_min = max(0, parcela_desejada - margem_parcela)
95
  parcela_max = parcela_desejada + margem_parcela
 
96
  return credito_min, credito_max, entrada_min, entrada_max, parcela_min, parcela_max
97
 
 
98
  def filtrar_cotas_por_faixa(cotas, credito_min, credito_max):
 
99
  return [c for c in cotas if c['valor_credito'] < credito_max * 2]
100
 
 
101
  def buscar_combinacoes_otimizado(credito_desejado, entrada_desejada, parcela_desejada, administradoras=None, max_combinacoes=15):
 
102
  global df_imovel, grupos_imovel
 
103
  if not planilha_carregada:
104
  if not carregar_planilha():
105
+ return "❌ Erro: Planilha não carregada."
 
 
106
  if administradoras and len(administradoras) > 0:
107
  grupos_filtrados = {adm: cotas for adm, cotas in grupos_imovel.items() if adm in administradoras}
108
  else:
109
  grupos_filtrados = grupos_imovel
 
110
  if not grupos_filtrados:
111
+ return "🚫 Nenhuma cota encontrada com os filtros aplicados."
 
 
 
 
112
  credito_min, credito_max, entrada_min, entrada_max, parcela_min, parcela_max = definir_margens_absolutas(
113
  credito_desejado, entrada_desejada, parcela_desejada
114
  )
 
 
 
 
 
115
  max_cotas_combinacao = 15
116
  max_combinacoes_por_adm = 4000
 
117
  resultados = []
118
  total_combinacoes_testadas = 0
 
119
  for adm, cotas in grupos_filtrados.items():
 
 
120
  cotas_filtradas = filtrar_cotas_por_faixa(cotas, credito_min, credito_max)
 
121
  for r in range(1, min(max_cotas_combinacao + 1, len(cotas_filtradas) + 1)):
122
  combinacoes_geradas = 0
123
  for combinacao in itertools.combinations(cotas_filtradas, r):
124
  if combinacoes_geradas >= max_combinacoes_por_adm:
125
  break
 
126
  total_combinacoes_testadas += 1
127
  combinacoes_geradas += 1
 
128
  total_credito = sum(c['valor_credito'] for c in combinacao)
129
  total_entrada_base = sum(c['valor_entrada'] for c in combinacao)
130
  total_entrada = total_entrada_base + (total_credito * 0.085)
131
  total_parcelas = sum(c['valor_parcela'] for c in combinacao)
 
132
  if (credito_min <= total_credito <= credito_max and
133
  entrada_min <= total_entrada <= entrada_max and
134
  parcela_min <= total_parcelas <= parcela_max):
 
135
  total_saldo = sum(c['saldo_devedor'] for c in combinacao)
136
  valor_final = round(total_entrada + total_saldo, 2)
137
  diferenca = abs(valor_final - total_credito)
 
138
  resultados.append((adm, combinacao, diferenca))
 
139
  if len(resultados) >= max_combinacoes * 2:
140
  break
 
141
  if len(resultados) >= max_combinacoes * 2:
142
  break
 
143
  if len(resultados) >= max_combinacoes * 2:
144
  break
 
 
 
 
145
  if not resultados:
146
+ return "🚫 Nenhuma combinação adequada encontrada."
 
147
  resultados.sort(key=lambda x: x[2])
148
  return formatar_resultados(resultados[:max_combinacoes])
149
 
 
150
  def formatar_resultados(resultados):
 
151
  if not resultados:
152
+ return "🚫 Nenhuma combinação adequada encontrada."
 
153
  resposta = ""
154
  for idx, (adm, combinacao, _) in enumerate(resultados, 1):
155
  codigos = [str(c.get('codigo', 'N/A')) for c in combinacao]
 
159
  total_saldo = sum(c['saldo_devedor'] for c in combinacao)
160
  total_parcelas = sum(c['valor_parcela'] for c in combinacao)
161
  maior_prazo = max(int(c.get('qtd_parcelas', 0)) for c in combinacao)
 
162
  valor_final = round(total_entrada + total_saldo, 2)
163
  credito_real = round(total_credito - total_entrada, 2)
164
  taxa_total = total_saldo - credito_real
165
  taxa_percentual = (taxa_total / credito_real) * 100 if credito_real > 0 else 0
166
  taxa_mensal = taxa_percentual / maior_prazo if maior_prazo > 0 else 0
 
167
  tempo_parcelas = calcular_tempo_parcelas(combinacao)
 
168
  resposta += f"""
169
  --- COMBINAÇÃO {idx} ---
170
  🏢 Administradora: {adm}
 
184
  """
185
  return resposta
186
 
 
 
187
  carregar_planilha()
188
 
 
189
  def ajustar_e_buscar(credito_desejado, entrada_desejada, parcela_desejada, administradoras):
190
  return buscar_combinacoes_otimizado(
191
  float(credito_desejado or 0),
 
195
  max_combinacoes=15
196
  )
197
 
 
198
  def get_administradoras_options():
199
  if df is not None and planilha_carregada:
200
  adm_list = df[df['tipo_do_bem'].str.lower() == 'imovel']['administradora'].unique()
201
  return sorted(adm_list)
202
  return []
203
 
204
+ # Interface Gradio
 
205
  with gr.Blocks(title="Sistema de Busca de Consórcio Imóvel") as demo:
206
  gr.HTML("""
207
  <link href="https://fonts.googleapis.com/css2?family=Poppins&display=swap" rel="stylesheet">
 
225
  .gr-button:hover { background-color: #fff3e0 !important; }
226
  </style>
227
  """)
 
228
  gr.Markdown("# 🏠 Busca de Combinações de Consórcio Imóvel")
229
  gr.Markdown("Insira os valores desejados para crédito, entrada e parcela, e filtre por administradora.")
 
230
  with gr.Row():
231
  credito_input = gr.Number(label="Crédito Desejado (R$)", value=300000, step=1000)
232
  entrada_input = gr.Number(label="Entrada Desejada (R$)", value=30000, step=1000)
233
  parcela_input = gr.Number(label="Parcela Desejada (R$)", value=1500, step=100)
 
234
  administradoras_multiselect = gr.CheckboxGroup(
235
  label="Filtrar por Administradoras",
236
  choices=get_administradoras_options(),
237
  value=get_administradoras_options()
238
  )
 
239
  submit_btn = gr.Button("🔍 Buscar Combinações", variant="primary")
240
  output_text = gr.Textbox(label="Resultados da Busca", lines=20, max_lines=40, interactive=False, placeholder="Os resultados aparecerão aqui...")
 
241
  submit_btn.click(
242
  fn=ajustar_e_buscar,
243
  inputs=[credito_input, entrada_input, parcela_input, administradoras_multiselect],
244
+ outputs=output_text,
245
+ api_name="buscar" # ← ENDPOINT CUSTOMIZADO
246
  )
 
247
  gr.Markdown("---")
248
  gr.Markdown("Desenvolvido para auxiliar na busca por cotas de consórcio ideais.")
249
 
250
+ # ===== CORS =====
 
 
251
  demo.app.add_middleware(
252
  CORSMiddleware,
253
  allow_origins=[
254
  "https://www.maxconconsorcios.com.br",
255
  "https://maxconconsorcios.com.br",
 
256
  ],
257
+ allow_credentials=True,
258
  allow_methods=["*"],
259
  allow_headers=["*"],
260
  )
261
 
 
 
262
  if __name__ == "__main__":
263
  demo.launch()