Arthur-Attili commited on
Commit
ba31397
·
verified ·
1 Parent(s): 961a30b

Update app.py

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