Persano commited on
Commit
1d0ca56
·
verified ·
1 Parent(s): 2435e8c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +47 -83
app.py CHANGED
@@ -15,21 +15,15 @@ from babel.numbers import format_currency
15
 
16
  app = Flask(__name__)
17
 
18
- # Configuração do logger
19
  logging.basicConfig(level=logging.DEBUG)
20
 
21
- # Configure sua chave da OpenAI via variável de ambiente
22
  openai.api_key = os.getenv("OPENAI_API_KEY")
23
 
24
- # Função para formatar valores monetários em BRL
25
  def formatar_brl(valor):
26
- try:
27
- return format_currency(valor, "BRL", locale="pt_BR")
28
- except Exception:
29
- logging.warning(f"Erro ao formatar valor monetário: {valor}")
30
- return f"R$ {valor:,.2f}"
31
 
32
- # Função para converter para float com log e valor default
33
  def safe_float(valor, nome, default=0.0):
34
  try:
35
  f = float(valor)
@@ -39,7 +33,6 @@ def safe_float(valor, nome, default=0.0):
39
  logging.error(f"Erro convertendo {nome} com valor '{valor}': {e}")
40
  return default
41
 
42
- # Função que calcula projeções para os 5 anos
43
  def calcular_projecoes(capital, studio_ret, valorizacao, franquia_ret, acoes_ret, renda_fixa):
44
  anos = list(range(1, 6))
45
  patrimonio_studio = [capital * ((1 + valorizacao / 100) ** ano) for ano in anos]
@@ -65,7 +58,6 @@ def calcular_projecoes(capital, studio_ret, valorizacao, franquia_ret, acoes_ret
65
  }
66
  return dados, investimentos_finais
67
 
68
- # Função para gerar gráfico base64
69
  def gerar_grafico(anos, studio_total, franquia, acoes, renda_fixa_valores):
70
  plt.figure(figsize=(8, 5))
71
  plt.plot(anos, studio_total, label="Studio (Patrimônio + Renda)", marker="o")
@@ -87,7 +79,6 @@ def gerar_grafico(anos, studio_total, franquia, acoes, renda_fixa_valores):
87
  grafico_base64 = base64.b64encode(buf.getvalue()).decode("utf-8")
88
  return grafico_base64
89
 
90
- # Função que gera o relatório com a API OpenAI
91
  def gerar_analise_ia(investimentos_finais, capital, patrimonio_studio_final):
92
  prompt = f"""
93
  Você é um analista financeiro experiente, e está redigindo um relatório para um cliente com capital inicial de R$ {capital:,.2f}. Após 5 anos, os resultados dos investimentos foram:
@@ -104,23 +95,18 @@ Escreva um relatório claro, didático e consultivo, com no máximo 10 linhas, c
104
  5. Sugestão de diversificação balanceada para perfil moderado.
105
  Use parágrafos e destaque em negrito os títulos dos tópicos. Não use markdown, apenas HTML.
106
  """
107
- try:
108
- resposta = openai.ChatCompletion.create(
109
- model="gpt-4o",
110
- messages=[
111
- {"role": "system", "content": "Você é um analista financeiro experiente."},
112
- {"role": "user", "content": prompt}
113
- ],
114
- max_tokens=500,
115
- temperature=0.7
116
- )
117
- texto = resposta.choices[0].message.content
118
- return texto
119
- except Exception as e:
120
- logging.error(f"Erro ao chamar API OpenAI: {e}")
121
- return "<p>Erro ao gerar análise com IA.</p>"
122
 
123
- # Função para gerar PDF a partir de template HTML
124
  def render_pdf(template_src, context_dict):
125
  html = render_template(template_src, **context_dict)
126
  result = io.BytesIO()
@@ -131,7 +117,6 @@ def render_pdf(template_src, context_dict):
131
  logging.error(f"Erro pisa.CreatePDF: {pisa_status.err}")
132
  return None
133
 
134
- # Rota principal com formulário
135
  @app.route("/", methods=["GET", "POST"])
136
  def index():
137
  if request.method == "POST":
@@ -176,72 +161,51 @@ def index():
176
  logging.error("Erro na rota /", exc_info=True)
177
  return "Erro interno no servidor. Verifique os logs.", 500
178
 
179
- # GET simples
180
  return render_template("index.html")
181
 
182
- # Rota para gerar PDF com relatório
183
- @app.route("/gerar-pdf", methods=["POST"])
184
- def gerar_pdf():
185
  try:
186
- campos = ["capital", "studio_ret", "valorizacao", "franquia_ret", "acoes_ret", "renda_fixa", "inflacao"]
187
- dados = {campo: safe_float(request.form.get(campo), campo) for campo in campos}
188
-
189
- capital = dados["capital"]
190
- anos = list(range(1, 6))
191
-
192
- patrimonio_studio = [capital * ((1 + dados["valorizacao"] / 100) ** ano) for ano in anos]
193
- renda_acumulada_studio = [capital * (((1 + dados["studio_ret"] / 100) ** (12 * ano)) - 1) for ano in anos]
194
- studio_total = [p + r for p, r in zip(patrimonio_studio, renda_acumulada_studio)]
195
- patrimonio_final = studio_total[-1]
196
-
197
- franquia = [capital + (dados["franquia_ret"] * ano) for ano in anos]
198
- acoes = [capital * ((1 + dados["acoes_ret"] / 100) ** ano) for ano in anos]
199
- renda_fixa_valores = [capital * ((1 + dados["renda_fixa"] / 100) ** ano) for ano in anos]
200
-
201
- df = pd.DataFrame({
202
- "Ano": anos,
203
- "Studio (Patrimônio + Renda)": studio_total,
204
- "Franquia": franquia,
205
- "Ações": acoes,
206
- "Renda Fixa": renda_fixa_valores
207
- })
208
-
209
- investimentos_finais = {
210
- "Studio": studio_total[-1],
211
- "Franquia": franquia[-1],
212
- "Ações": acoes[-1],
213
- "Renda Fixa": renda_fixa_valores[-1]
214
- }
215
 
216
- grafico_base64 = gerar_grafico(anos, studio_total, franquia, acoes, renda_fixa_valores)
 
 
 
 
 
 
 
 
217
 
 
 
 
 
 
 
 
218
  df_formatado = df.copy()
219
  for col in df.columns:
220
  if col != "Ano":
221
  df_formatado[col] = df_formatado[col].apply(formatar_brl)
222
- tabela_html = df_formatado.to_html(index=False, classes="tabela", border=0)
 
 
223
 
224
- analise_final = gerar_analise_ia(investimentos_finais, capital, patrimonio_final)
225
 
226
  data_formatada = format_date(datetime.now(), "d 'de' MMMM 'de' yyyy", locale="pt_BR")
227
  data_hoje = f"São Paulo, {data_formatada}"
228
 
229
- capital_formatado = formatar_brl(capital)
230
- studio_ret_formatado = f"{dados['studio_ret']:.2f} %"
231
- valorizacao_formatado = f"{dados['valorizacao']:.2f} %"
232
- franquia_ret_formatado = formatar_brl(dados["franquia_ret"])
233
- acoes_ret_formatado = f"{dados['acoes_ret']:.2f} %"
234
- renda_fixa_formatado = f"{dados['renda_fixa']:.2f} %"
235
- inflacao_formatado = f"{dados['inflacao']:.2f} %"
236
-
237
  context = {
238
- "capital_formatado": capital_formatado,
239
- "studio_ret_formatado": studio_ret_formatado,
240
- "valorizacao_formatado": valorizacao_formatado,
241
- "franquia_ret_formatado": franquia_ret_formatado,
242
- "acoes_ret_formatado": acoes_ret_formatado,
243
- "renda_fixa_formatado": renda_fixa_formatado,
244
- "inflacao_formatado": inflacao_formatado,
245
  "grafico": grafico_base64,
246
  "tabela": tabela_html,
247
  "analise_final": analise_final,
@@ -254,9 +218,9 @@ def gerar_pdf():
254
  else:
255
  return "Erro ao gerar o PDF", 500
256
 
257
- except Exception as e:
258
- logging.error("Erro na rota /gerar-pdf", exc_info=True)
259
- return f"Erro interno ao gerar o PDF:\n{str(e)}", 500
260
 
261
 
262
  if __name__ == "__main__":
 
15
 
16
  app = Flask(__name__)
17
 
18
+ # Logger
19
  logging.basicConfig(level=logging.DEBUG)
20
 
21
+ # OpenAI key da variável de ambiente
22
  openai.api_key = os.getenv("OPENAI_API_KEY")
23
 
 
24
  def formatar_brl(valor):
25
+ return format_currency(valor, "BRL", locale="pt_BR")
 
 
 
 
26
 
 
27
  def safe_float(valor, nome, default=0.0):
28
  try:
29
  f = float(valor)
 
33
  logging.error(f"Erro convertendo {nome} com valor '{valor}': {e}")
34
  return default
35
 
 
36
  def calcular_projecoes(capital, studio_ret, valorizacao, franquia_ret, acoes_ret, renda_fixa):
37
  anos = list(range(1, 6))
38
  patrimonio_studio = [capital * ((1 + valorizacao / 100) ** ano) for ano in anos]
 
58
  }
59
  return dados, investimentos_finais
60
 
 
61
  def gerar_grafico(anos, studio_total, franquia, acoes, renda_fixa_valores):
62
  plt.figure(figsize=(8, 5))
63
  plt.plot(anos, studio_total, label="Studio (Patrimônio + Renda)", marker="o")
 
79
  grafico_base64 = base64.b64encode(buf.getvalue()).decode("utf-8")
80
  return grafico_base64
81
 
 
82
  def gerar_analise_ia(investimentos_finais, capital, patrimonio_studio_final):
83
  prompt = f"""
84
  Você é um analista financeiro experiente, e está redigindo um relatório para um cliente com capital inicial de R$ {capital:,.2f}. Após 5 anos, os resultados dos investimentos foram:
 
95
  5. Sugestão de diversificação balanceada para perfil moderado.
96
  Use parágrafos e destaque em negrito os títulos dos tópicos. Não use markdown, apenas HTML.
97
  """
98
+ resposta = openai.ChatCompletion.create(
99
+ model="gpt-4o",
100
+ messages=[
101
+ {"role": "system", "content": "Você é um analista financeiro experiente."},
102
+ {"role": "user", "content": prompt}
103
+ ],
104
+ max_tokens=500,
105
+ temperature=0.7
106
+ )
107
+ texto = resposta.choices[0].message.content
108
+ return texto
 
 
 
 
109
 
 
110
  def render_pdf(template_src, context_dict):
111
  html = render_template(template_src, **context_dict)
112
  result = io.BytesIO()
 
117
  logging.error(f"Erro pisa.CreatePDF: {pisa_status.err}")
118
  return None
119
 
 
120
  @app.route("/", methods=["GET", "POST"])
121
  def index():
122
  if request.method == "POST":
 
161
  logging.error("Erro na rota /", exc_info=True)
162
  return "Erro interno no servidor. Verifique os logs.", 500
163
 
 
164
  return render_template("index.html")
165
 
166
+ @app.route("/relatorio", methods=["POST"])
167
+ def relatorio():
 
168
  try:
169
+ logging.debug(f"Dados recebidos para PDF: {request.form}")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
170
 
171
+ capital = safe_float(request.form.get("capital"), "capital")
172
+ studio_ret = safe_float(request.form.get("studio_ret"), "studio_ret")
173
+ valorizacao = safe_float(request.form.get("valorizacao"), "valorizacao")
174
+ franquia_ret = safe_float(request.form.get("franquia_ret"), "franquia_ret")
175
+ acoes_ret = safe_float(request.form.get("acoes_ret"), "acoes_ret")
176
+ renda_fixa = safe_float(request.form.get("renda_fixa"), "renda_fixa")
177
+ inflacao = safe_float(request.form.get("inflacao"), "inflacao")
178
+
179
+ dados, investimentos_finais = calcular_projecoes(capital, studio_ret, valorizacao, franquia_ret, acoes_ret, renda_fixa)
180
 
181
+ anos = dados["Ano"]
182
+ studio_total = dados["Studio (Patrimônio + Renda)"]
183
+ franquia = dados["Franquia"]
184
+ acoes = dados["Ações"]
185
+ renda_fixa_valores = dados["Renda Fixa"]
186
+
187
+ df = pd.DataFrame(dados)
188
  df_formatado = df.copy()
189
  for col in df.columns:
190
  if col != "Ano":
191
  df_formatado[col] = df_formatado[col].apply(formatar_brl)
192
+ tabela_html = df_formatado.to_html(index=False, classes="table table-striped table-sm text-end", border=0)
193
+
194
+ grafico_base64 = gerar_grafico(anos, studio_total, franquia, acoes, renda_fixa_valores)
195
 
196
+ analise_final = gerar_analise_ia(investimentos_finais, capital, studio_total[-1])
197
 
198
  data_formatada = format_date(datetime.now(), "d 'de' MMMM 'de' yyyy", locale="pt_BR")
199
  data_hoje = f"São Paulo, {data_formatada}"
200
 
 
 
 
 
 
 
 
 
201
  context = {
202
+ "capital_formatado": formatar_brl(capital),
203
+ "studio_ret_formatado": f"{studio_ret:.2f} %",
204
+ "valorizacao_formatado": f"{valorizacao:.2f} %",
205
+ "franquia_ret_formatado": formatar_brl(franquia_ret),
206
+ "acoes_ret_formatado": f"{acoes_ret:.2f} %",
207
+ "renda_fixa_formatado": f"{renda_fixa:.2f} %",
208
+ "inflacao_formatado": f"{inflacao:.2f} %",
209
  "grafico": grafico_base64,
210
  "tabela": tabela_html,
211
  "analise_final": analise_final,
 
218
  else:
219
  return "Erro ao gerar o PDF", 500
220
 
221
+ except Exception:
222
+ logging.error("Erro na rota /relatorio", exc_info=True)
223
+ return "Erro interno ao gerar o PDF. Verifique os logs.", 500
224
 
225
 
226
  if __name__ == "__main__":