Arthur-Attili commited on
Commit
44de8f1
·
verified ·
1 Parent(s): becdb30

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +304 -202
app.py CHANGED
@@ -1,210 +1,312 @@
1
  import os
 
 
 
 
2
  import requests
3
- import json
4
- from flask import Flask, request, jsonify
5
- from flask_cors import CORS
6
- from functools import lru_cache
7
- from datetime import datetime
8
- import logging
9
-
10
- # ==================== CONFIGURAÇÃO ====================
11
- logging.basicConfig(level=logging.DEBUG)
12
- logger = logging.getLogger(__name__)
13
-
14
- app = Flask(__name__)
15
- CORS(app, origins=["https://www.maxconconsorcios.com.br", "https://vendasuacota.com.br"])
16
-
17
- # ==================== CONFIGURAÇÃO DA API REAL ====================
18
- API_BASE_URL = "https://api.maxconconsorcios.com.br"
19
- WHATSAPP_NUMBER = "5516997865738"
20
-
21
- # ==================== FUNÇÕES AUXILIARES ====================
22
- def format_currency(value):
23
- """Formata valor para moeda brasileira"""
24
- if value is None:
25
- return "R$ 0,00"
26
- return f"R$ {float(value):,.2f}".replace(",", "v").replace(".", ",").replace("v", ".")
27
-
28
- def calcular_entrada_total(cota):
29
- """Calcula entrada total incluindo comissão de 8.5%"""
30
- credito = float(cota.get('valor_credito', 0))
31
- entrada = float(cota.get('entrada', 0))
32
- comissao = credito * 0.085
33
- return entrada + comissao
34
-
35
- def get_administradora_nome(admin_id):
36
- """Mapeia ID da administradora para nome"""
37
- admin_map = {
38
- 1:'Itaú', 2:'Bradesco', 3:'Santander', 4:'Honda', 5:'Volkswagen',
39
- 6:'Serello', 7:'Ademicon', 8:'Remaza', 9:'Porto Seguro VP',
40
- 10:'Banrisul', 11:'Embracon', 12:'Serrana', 13:'Caixa XS5',
41
- 14:'Caixa CNP', 15:'Unifisa', 16:'HS Consorcios', 17:'Caixa Seguradora',
42
- 18:'Porto Seguro', 19:'Mycon', 20:'Rodobens', 21:'Ford',
43
- 22:'Sicoob Unicoob', 23:'Zema', 24:'Maggi', 25:'Ancora', 26:'Yamaha',
44
- 27:'Sponchiado', 28:'Scania', 29:'Disal', 30:'Servopa', 31:'Canopus',
45
- 32:'Bradesco', 33:'Banco do Brasil', 34:'Santander', 35:'Sicredi'
46
- }
47
- return admin_map.get(admin_id, 'Não especificado')
48
-
49
- # ==================== ROTA PRINCIPAL ====================
50
- @app.route('/api/buscar_combinacoes', methods=['POST'])
51
- def buscar_combinacoes():
52
- """
53
- Endpoint que busca combinações de cotas usando a API real
54
- (mesmo backend da Foto 1)
55
- """
56
- try:
57
- data = request.get_json()
58
-
59
- produto = data.get('produto', 'moto')
60
- credito_min = float(data.get('credito', 0))
61
- entrada_max = float(data.get('entrada', 0))
62
- parcela_max = float(data.get('parcela', 0))
63
- administradoras = data.get('administradoras', [])
64
-
65
- logger.info(f"Buscando combinações para {produto} com crédito mínimo R$ {credito_min:,.2f}")
66
-
67
- # Mapeamento de categorias
68
- categoria = 'veiculo' if produto in ['moto', 'carro', 'caminhao'] else 'imovel'
69
-
70
- # Busca cotas na API real
71
- response = requests.post(
72
- f"{API_BASE_URL}/api/cotas",
73
- json={
74
- 'categoria': categoria,
75
- 'valor_credito_min': credito_min if credito_min > 0 else None,
76
- 'valor_parcela_max': parcela_max if parcela_max > 0 else None
77
- }
78
- )
79
-
80
- if response.status_code != 200:
81
- return jsonify({'error': 'Erro ao buscar cotas'}), 500
82
-
83
- cotas = response.json()
84
-
85
- # Filtra por administradora
86
- if administradoras:
87
- admin_ids = []
88
- for admin_nome in administradoras:
89
- for admin_id, nome in get_admin_map().items():
90
- if nome.lower() == admin_nome.lower():
91
- admin_ids.append(admin_id)
92
- break
93
-
94
- if admin_ids:
95
- cotas = [c for c in cotas if c.get('administradora_id') in admin_ids]
96
-
97
- # Filtra disponíveis
98
- cotas = [c for c in cotas if c.get('reserva') != 'reservado']
99
-
100
- # Filtra por entrada máxima
101
- if entrada_max > 0:
102
- cotas = [c for c in cotas if calcular_entrada_total(c) <= entrada_max]
103
-
104
- # Ordena por crédito
105
- cotas.sort(key=lambda x: float(x.get('valor_credito', 0)))
106
-
107
- # Gera combinações
108
- resultados = []
109
-
110
- for cota in cotas[:30]: # Limita para performance
111
- entrada_total = calcular_entrada_total(cota)
112
-
113
- if parcela_max > 0 and float(cota.get('valor_parcela', 0)) > parcela_max:
114
- continue
115
-
116
- resultado = {
117
- 'administradora': get_administradora_nome(cota.get('administradora_id')),
118
- 'codigo': cota.get('codigo'),
119
- 'credito': float(cota.get('valor_credito', 0)),
120
- 'entrada_total': entrada_total,
121
- 'parcela': float(cota.get('valor_parcela', 0)),
122
- 'prazo': cota.get('parcelas', 0),
123
- 'saldo_devedor': float(cota.get('saldo', 0)),
124
- 'categoria': categoria
125
- }
126
-
127
- # Adiciona campos extras
128
- credito_real = resultado['credito'] - entrada_total
129
- taxa_total = resultado['saldo_devedor'] - credito_real
130
- taxa_percentual = (taxa_total / credito_real * 100) if credito_real > 0 else 0
131
-
132
- resultado['credito_liquido'] = credito_real
133
- resultado['taxa_total'] = taxa_total
134
- resultado['taxa_percentual'] = taxa_percentual
135
- resultado['valor_final'] = entrada_total + resultado['saldo_devedor']
136
-
137
- # Taxas mensal e anual
138
- if resultado['prazo'] > 0:
139
- resultado['taxa_mensal'] = taxa_percentual / resultado['prazo']
140
- resultado['taxa_anual'] = resultado['taxa_mensal'] * 12
141
- else:
142
- resultado['taxa_mensal'] = 0
143
- resultado['taxa_anual'] = 0
144
-
145
- # Tempo de parcelas (escalonado)
146
- if resultado['prazo'] > 21:
147
- resultado['parcelas_1a21'] = resultado['parcela']
148
- resultado['parcelas_22a27'] = resultado['parcela'] * 0.44
149
- else:
150
- resultado['parcelas_1a21'] = resultado['parcela']
151
- resultado['parcelas_22a27'] = 0
152
-
153
- resultados.append(resultado)
154
-
155
- return jsonify({
156
- 'status': 'success',
157
- 'combinacoes': resultados[:15],
158
- 'total_encontrado': len(resultados)
159
- })
160
-
161
- except Exception as e:
162
- logger.error(f"Erro em buscar_combinacoes: {str(e)}")
163
- return jsonify({'error': str(e)}), 500
164
 
165
- @app.route('/api/detalhes_cota/<int:cota_id>', methods=['GET'])
166
- def detalhes_cota(cota_id):
167
- """Proxy para o endpoint de detalhes da API real"""
168
  try:
169
- response = requests.get(f"{API_BASE_URL}/api/detalhes_cota/{cota_id}")
170
- return jsonify(response.json()), response.status_code
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
171
  except Exception as e:
172
- return jsonify({'error': str(e)}), 500
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
173
 
174
- @app.route('/api/somar_cotas', methods=['POST'])
175
- def somar_cotas():
176
- """Proxy para o endpoint de soma da API real"""
177
  try:
178
- response = requests.post(
179
- f"{API_BASE_URL}/api/somar_cotas",
180
- json=request.get_json(),
181
- headers={'Content-Type': 'application/json'}
182
- )
183
- return jsonify(response.json()), response.status_code
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
184
  except Exception as e:
185
- return jsonify({'error': str(e)}), 500
186
-
187
- @app.route('/health', methods=['GET'])
188
- def health_check():
189
- """Endpoint de saúde"""
190
- return jsonify({
191
- 'status': 'healthy',
192
- 'timestamp': datetime.now().isoformat(),
193
- 'api_connected': True
194
- }), 200
195
-
196
- def get_admin_map():
197
- """Retorna mapeamento de administradoras"""
198
- return {
199
- 1: 'Itaú', 2: 'Bradesco', 3: 'Santander', 4: 'Honda', 5: 'Volkswagen',
200
- 6: 'Serello', 7: 'Ademicon', 8: 'Remaza', 9: 'Porto Seguro VP',
201
- 10: 'Banrisul', 11: 'Embracon', 12: 'Serrana', 13: 'Caixa XS5',
202
- 14: 'Caixa CNP', 15: 'Unifisa', 16: 'HS Consorcios', 17: 'Caixa Seguradora',
203
- 18: 'Porto Seguro', 19: 'Mycon', 20: 'Rodobens', 21: 'Ford',
204
- 22: 'Sicoob Unicoob', 23: 'Zema', 24: 'Maggi', 25: 'Ancora', 26: 'Yamaha',
205
- 27: 'Sponchiado', 28: 'Scania', 29: 'Disal', 30: 'Servopa', 31: 'Canopus',
206
- 32: 'Bradesco', 33: 'Banco do Brasil', 34: 'Santander', 35: 'Sicredi'
207
- }
208
-
209
- if __name__ == '__main__':
210
- app.run(host='0.0.0.0', port=5003, debug=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import os
2
+ os.environ["GRADIO_ANALYTICS_ENABLED"] = "False"
3
+ os.environ["HF_HUB_DISABLE_TELEMETRY"] = "1"
4
+
5
+ import pandas as pd
6
  import requests
7
+ import io
8
+ import itertools
9
+ from collections import defaultdict
10
+ import gradio as gr
11
+
12
+ # 🔧 CONFIGURAÇÕES DO ARQUIVO
13
+ FILE_ID = "1EoH8V3Fyls0mNa95VcBN6ZL1B552ty3X"
14
+ URL = f"https://drive.google.com/uc?export=download&id={FILE_ID}"
15
+
16
+ # Variáveis globais
17
+ df_auto = None
18
+ grupos_auto = None
19
+ planilha_carregada = False
20
+ ADMIN_OPCOES = []
21
+
22
+
23
+ def carregar_planilha():
24
+ global df_auto, grupos_auto, planilha_carregada, ADMIN_OPCOES
25
+
26
+ if planilha_carregada:
27
+ return True
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
 
 
 
 
29
  try:
30
+ print("⏳ Carregando planilha de automóveis...")
31
+ response = requests.get(URL)
32
+ response.raise_for_status()
33
+ data = io.BytesIO(response.content)
34
+ df = pd.read_excel(data)
35
+
36
+ df.columns = df.columns.str.strip().str.lower().str.replace(" ", "_")
37
+
38
+ colunas_numericas = ['valor_credito', 'valor_entrada', 'valor_parcela', 'saldo_devedor', 'qtd_parcelas']
39
+ for col in colunas_numericas:
40
+ if col in df.columns:
41
+ df[col] = pd.to_numeric(df[col], errors='coerce').fillna(0)
42
+
43
+ if 'tipo_do_bem' not in df.columns or 'administradora' not in df.columns:
44
+ raise ValueError("Colunas essenciais não encontradas")
45
+
46
+ df.drop_duplicates(inplace=True)
47
+
48
+ df_auto = df[df['tipo_do_bem'].str.lower() == 'auto'].copy()
49
+ df_auto['administradora'] = df_auto['administradora'].astype(str).str.strip().str.lower()
50
+ df_auto = df_auto[df_auto['administradora'].notna() & (df_auto['administradora'] != '')]
51
+
52
+ grupos_auto = defaultdict(list)
53
+ for _, row in df_auto.iterrows():
54
+ grupos_auto[row['administradora']].append(row.to_dict())
55
+
56
+ ADMIN_OPCOES = sorted(df_auto['administradora'].unique())
57
+ planilha_carregada = True
58
+
59
+ print(f"✅ Total de cotas AUTO: {len(df_auto)}")
60
+ print(f"✅ Administradoras AUTO: {ADMIN_OPCOES}")
61
+ return True
62
+
63
  except Exception as e:
64
+ print(f"❌ Erro ao carregar planilha AUTO: {e}")
65
+ return False
66
+
67
+
68
+ def formatar_moeda(valor):
69
+ return f"R$ {valor:,.2f}".replace(",", "v").replace(".", ",").replace("v", ".")
70
+
71
+
72
+ def definir_margens_absolutas(credito, entrada, parcela):
73
+ margem_credito = 20_000 # ex.: 30.000 → 10.000–50.000
74
+ margem_entrada = 2_000
75
+ margem_parcela = 100
76
+
77
+ cred_min = max(0, credito - margem_credito)
78
+ cred_max = credito + margem_credito
79
+ ent_min = max(0, entrada - margem_entrada)
80
+ ent_max = entrada + margem_entrada
81
+ parc_min = max(0, parcela - margem_parcela)
82
+ parc_max = parcela + margem_parcela
83
+
84
+ return cred_min, cred_max, ent_min, ent_max, parc_min, parc_max
85
+
86
+
87
+ def filtrar_cotas_por_faixa(cotas, cred_min, cred_max):
88
+ return [c for c in cotas if c['valor_credito'] < cred_max * 2]
89
+
90
+
91
+ def calcular_tempo_parcelas(combinacao):
92
+ if not combinacao:
93
+ return ""
94
 
 
 
 
95
  try:
96
+ cotas_ordenadas = sorted(combinacao, key=lambda x: int(x.get('qtd_parcelas', 0)))
97
+ prazos = sorted(set(int(c.get('qtd_parcelas', 0)) for c in combinacao))
98
+
99
+ if not prazos or prazos[0] <= 0:
100
+ return ""
101
+
102
+ resultado = []
103
+ prazo_anterior = 0
104
+
105
+ for prazo_atual in prazos:
106
+ cotas_ativas = [c for c in cotas_ordenadas if int(c.get('qtd_parcelas', 0)) >= prazo_anterior + 1]
107
+ valor_parcela_total = sum(c.get('valor_parcela', 0) for c in cotas_ativas)
108
+
109
+ inicio = prazo_anterior + 1
110
+ fim = prazo_atual
111
+
112
+ if inicio <= fim and valor_parcela_total > 0:
113
+ resultado.append(f"{inicio}x à {fim}x: {formatar_moeda(valor_parcela_total)}/mês")
114
+
115
+ prazo_anterior = prazo_atual
116
+
117
+ if prazos and prazo_anterior < max(prazos):
118
+ cotas_ativas_finais = [c for c in cotas_ordenadas if int(c.get('qtd_parcelas', 0)) > prazo_anterior]
119
+ if cotas_ativas_finais:
120
+ valor_parcela_final = sum(c.get('valor_parcela', 0) for c in cotas_ativas_finais)
121
+ inicio_final = prazo_anterior + 1
122
+ fim_final = max(prazos)
123
+ if valor_parcela_final > 0:
124
+ resultado.append(f"{inicio_final}x à {fim_final}x: {formatar_moeda(valor_parcela_final)}/mês")
125
+
126
+ return "\\n".join(resultado) if resultado else ""
127
+
128
  except Exception as e:
129
+ print(f"❌ Erro calcular tempo de parcelas AUTO: {e}")
130
+ return ""
131
+
132
+
133
+ def buscar_combinacoes(credito, entrada, parcela, adm_selecionadas):
134
+ if not planilha_carregada:
135
+ if not carregar_planilha():
136
+ return "❌ Erro: planilha de automóveis não carregada."
137
+
138
+ # Filtra administradoras
139
+ if adm_selecionadas:
140
+ grupos = {adm: cotas for adm, cotas in grupos_auto.items() if adm in adm_selecionadas}
141
+ else:
142
+ grupos = grupos_auto
143
+
144
+ if not grupos:
145
+ return "🚫 Nenhuma cota de automóvel encontrada com os filtros."
146
+
147
+ # Margens absolutas
148
+ cred_min, cred_max, ent_min, ent_max, parc_min, parc_max = definir_margens_absolutas(
149
+ float(credito or 0),
150
+ float(entrada or 0),
151
+ float(parcela or 0)
152
+ )
153
+
154
+ print(f"💰 AUTO - Crédito: R$ {credito:,.2f} → [{cred_min:,.2f}, {cred_max:,.2f}]")
155
+
156
+ # Limites de busca
157
+ max_cotas_combinacao = 15
158
+ max_combinacoes_por_adm = 4000
159
+
160
+ resultados = []
161
+ total_combinacoes_testadas = 0
162
+
163
+ for adm, cotas in grupos.items():
164
+ print(f"🔍 AUTO - Administradora: {adm} ({len(cotas)} cotas)")
165
+ cotas_filtradas = filtrar_cotas_por_faixa(cotas, cred_min, cred_max)
166
+
167
+ for r in range(1, min(max_cotas_combinacao + 1, len(cotas_filtradas) + 1)):
168
+ combinacoes_geradas = 0
169
+ for combinacao in itertools.combinations(cotas_filtradas, r):
170
+ if combinacoes_geradas >= max_combinacoes_por_adm:
171
+ break
172
+
173
+ total_combinacoes_testadas += 1
174
+ combinacoes_geradas += 1
175
+
176
+ total_cred = sum(c['valor_credito'] for c in combinacao)
177
+ total_ent_base = sum(c['valor_entrada'] for c in combinacao)
178
+ total_ent = total_ent_base + total_cred * 0.085
179
+ total_parc = sum(c['valor_parcela'] for c in combinacao)
180
+
181
+ if (cred_min <= total_cred <= cred_max and
182
+ ent_min <= total_ent <= ent_max and
183
+ parc_min <= total_parc <= parc_max):
184
+
185
+ total_saldo = sum(c['saldo_devedor'] for c in combinacao)
186
+ valor_final = round(total_ent + total_saldo, 2)
187
+ diff = abs(valor_final - total_cred)
188
+ resultados.append((adm, combinacao, diff))
189
+
190
+ if len(resultados) >= 45:
191
+ break
192
+ if len(resultados) >= 45:
193
+ break
194
+ if len(resultados) >= 45:
195
+ break
196
+
197
+ print(f"🔍 AUTO - Total de combinações testadas: {total_combinacoes_testadas}")
198
+
199
+ if not resultados:
200
+ return "🚫 Nenhuma combinação de auto encontrada com os parâmetros fornecidos."
201
+
202
+ resultados.sort(key=lambda x: x[2])
203
+ return formatar_resultados(resultados[:15])
204
+
205
+
206
+ def formatar_resultados(resultados):
207
+ if not resultados:
208
+ return "🚫 Nenhuma combinação de auto adequada encontrada."
209
+
210
+ resposta = ""
211
+ for idx, (adm, comb, _) in enumerate(resultados, 1):
212
+ codigos = [str(c.get('codigo', 'N/A')) for c in comb]
213
+ total_cred = sum(c['valor_credito'] for c in comb)
214
+ total_ent_base = sum(c['valor_entrada'] for c in comb)
215
+ total_ent = total_ent_base + total_cred * 0.085
216
+ total_saldo = sum(c['saldo_devedor'] for c in comb)
217
+ total_parc = sum(c['valor_parcela'] for c in comb)
218
+ maior_prazo = max(int(c.get('qtd_parcelas', 0)) for c in comb)
219
+ valor_final = round(total_ent + total_saldo, 2)
220
+ cred_real = total_cred - total_ent
221
+ taxa_total = total_saldo - cred_real
222
+ taxa_perc = (taxa_total / cred_real) * 100 if cred_real > 0 else 0
223
+ taxa_mensal = taxa_perc / maior_prazo if maior_prazo > 0 else 0
224
+ tempo = calcular_tempo_parcelas(comb)
225
+
226
+ resposta += f"""
227
+ --- COMBINAÇÃO {idx} AUTO ---
228
+ 🏢 Administradora: {adm}
229
+ 🔢 Códigos: {', '.join(codigos)} ({len(comb)} cotas)
230
+ 💰 Crédito Total: {formatar_moeda(total_cred)}
231
+ 💵 Entrada (+comissão): {formatar_moeda(total_ent)}
232
+ 📉 Saldo Devedor: {formatar_moeda(total_saldo)}
233
+ 💲 Parcela: {formatar_moeda(total_parc)}
234
+ ⏳ Prazo: {maior_prazo} meses
235
+ 🔚 Valor Final: {formatar_moeda(valor_final)}
236
+ 💠 Crédito Líquido: {formatar_moeda(cred_real)}
237
+ 📊 Taxa Total: {taxa_perc:.2f}% ({formatar_moeda(taxa_total)})
238
+ 🗓️ Taxa Mensal: {taxa_mensal:.2f}%
239
+ 🗓️ Taxa Anual: {taxa_mensal * 12:.2f}%
240
+ ⏰ TEMPO DE PARCELAS:
241
+ {tempo if tempo else "Não foi possível calcular"}
242
+ """
243
+ return resposta
244
+
245
+
246
+ # 🔁 Carregar a planilha uma vez, no início do programa
247
+ carregar_planilha()
248
+
249
+
250
+ # Interface Gradio (exatamente igual ao imóvel, com Blocks)
251
+ with gr.Blocks(title="🚗 Sistema de Busca de Consórcio Auto") as demo_auto:
252
+ gr.HTML("""
253
+ <link href="https://fonts.googleapis.com/css2?family=Poppins&display=swap" rel="stylesheet">
254
+ <style>
255
+ * { font-family: 'Poppins', sans-serif !important; }
256
+ body { background-color: #ff8f00 !important; color: black !important; }
257
+ input[type="number"], textarea {
258
+ background-color: white !important;
259
+ border: 2px solid black !important;
260
+ border-radius: 12px !important;
261
+ color: black !important;
262
+ padding: 10px !important;
263
+ }
264
+ .gr-button {
265
+ font-weight: bold;
266
+ border-radius: 10px !important;
267
+ background-color: white !important;
268
+ color: black !important;
269
+ border: 2px solid black !important;
270
+ }
271
+ </style>
272
+ """)
273
+
274
+ gr.Markdown("# 🚗 Busca de Combinações de Consórcio Auto")
275
+ gr.Markdown("Insira os valores desejados para crédito, entrada e parcela, e filtre por administradora.")
276
+
277
+ with gr.Row():
278
+ credito_input = gr.Number(label="Crédito Desejado (R$)", value=30000, step=1000)
279
+ entrada_input = gr.Number(label="Entrada Desejada (R$)", value=3000, step=100)
280
+ parcela_input = gr.Number(label="Parcela Desejada (R$)", value=500, step=10)
281
+
282
+ adm_input = gr.Dropdown(
283
+ choices=ADMIN_OPCOES,
284
+ label="Filtrar por Administradoras",
285
+ multiselect=True,
286
+ value=ADMIN_OPCOES,
287
+ interactive=True
288
+ )
289
+
290
+ submit_btn = gr.Button("🔍 Buscar Combinações AUTO", variant="primary")
291
+ output_text = gr.Textbox(
292
+ label="Resultados AUTO",
293
+ lines=20,
294
+ max_lines=40,
295
+ interactive=False,
296
+ placeholder="Os resultados aparecerão aqui..."
297
+ )
298
+
299
+ submit_btn.click(
300
+ fn=buscar_combinacoes,
301
+ inputs=[credito_input, entrada_input, parcela_input, adm_input],
302
+ outputs=output_text
303
+ )
304
+
305
+ gr.Markdown("---")
306
+ gr.Markdown("Desenvolvido para auxiliar na busca por cotas de consórcio automotivo.")
307
+
308
+
309
+ # Executar o app
310
+ if __name__ == "__main__":
311
+ demo_auto.launch()
312
+ #