Persano commited on
Commit
9b18e84
·
verified ·
1 Parent(s): 4e0fbb5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +271 -277
app.py CHANGED
@@ -4,170 +4,51 @@ import os
4
  os.environ['FONTCONFIG_PATH'] = '/tmp/fontconfig'
5
  os.makedirs('/tmp/fontconfig', exist_ok=True)
6
 
 
 
 
7
 
8
- from flask import Flask, render_template, request, send_file
9
  import matplotlib.pyplot as plt
 
10
  import io
11
  import base64
 
 
12
  from datetime import datetime
13
- import pandas as pd
14
 
15
  app = Flask(__name__)
16
 
17
- # Função para formatar valor em reais
18
  def formatar_brl(valor):
19
  return f"R$ {valor:,.2f}".replace(",", "X").replace(".", ",").replace("X", ".")
20
 
21
- # Função para gerar gráfico e retornar base64
22
- def gerar_grafico(valores, labels):
23
- plt.figure(figsize=(8,4))
24
- for label in labels:
25
- plt.plot(valores['Ano'], valores[label], label=label)
26
- plt.title("Projeção dos Investimentos ao longo dos anos")
27
- plt.xlabel("Ano")
28
- plt.ylabel("Valor (R$)")
29
- plt.legend()
30
- plt.grid(True)
31
- plt.tight_layout()
32
-
33
- img = io.BytesIO()
34
- plt.savefig(img, format='png')
35
- plt.close()
36
- img.seek(0)
37
- img_base64 = base64.b64encode(img.getvalue()).decode()
38
- return img_base64
 
 
 
 
39
 
40
- # Rota principal com formulário e relatório
41
  @app.route("/", methods=["GET", "POST"])
42
  def index():
43
  if request.method == "POST":
44
- try:
45
- capital = float(request.form["capital"])
46
- studio_ret = float(request.form["studio_ret"])
47
- valorizacao = float(request.form["valorizacao"])
48
- franquia_ret = float(request.form["franquia_ret"])
49
- acoes_ret = float(request.form["acoes_ret"])
50
- renda_fixa = float(request.form["renda_fixa"])
51
- inflacao = float(request.form["inflacao"])
52
- anos = int(request.form["anos"])
53
-
54
- # Cálculo dos valores ao longo dos anos
55
- anos_lista = list(range(0, anos + 1))
56
-
57
- df = pd.DataFrame({"Ano": anos_lista})
58
- # Studio: capital * (1 + retorno + valorização)^ano
59
- df["Studio"] = capital * ((1 + (studio_ret + valorizacao)/100) ** df["Ano"])
60
- # Franquia: capital + retorno fixo anual * ano
61
- df["Franquia"] = capital + franquia_ret * df["Ano"]
62
- # Ações: capital * (1 + retorno)^ano
63
- df["Ações"] = capital * ((1 + acoes_ret/100) ** df["Ano"])
64
- # Renda Fixa: capital * (1 + retorno)^ano
65
- df["Renda Fixa"] = capital * ((1 + renda_fixa/100) ** df["Ano"])
66
-
67
- # Valores finais para comparação
68
- valores_finais = df.iloc[-1, 1:]
69
- investimento_mais_valorizado = valores_finais.idxmax()
70
- valor_mais_alto = valores_finais.max()
71
-
72
- # Preparar resumo tabela
73
- resumo = []
74
- for investimento in ["Studio", "Franquia", "Ações", "Renda Fixa"]:
75
- valor_final = valores_finais[investimento]
76
- retorno_abs = valor_final - capital
77
- retorno_pct = (retorno_abs / capital) * 100
78
- resumo.append({
79
- "Investimento": investimento,
80
- "Valor Final": formatar_brl(valor_final),
81
- "Retorno Absoluto": formatar_brl(retorno_abs),
82
- "Retorno (%)": f"{retorno_pct:.2f}%"
83
- })
84
-
85
- # Montar tabela html para PDF
86
- tabela_html = """
87
- <table>
88
- <thead>
89
- <tr>
90
- <th style="text-align:left;">Investimento</th>
91
- <th>Valor Final</th>
92
- <th>Retorno Absoluto</th>
93
- <th>Retorno (%)</th>
94
- </tr>
95
- </thead>
96
- <tbody>
97
- """
98
- for r in resumo:
99
- tabela_html += f"""
100
- <tr>
101
- <td style="text-align:left;">{r['Investimento']}</td>
102
- <td>{r['Valor Final']}</td>
103
- <td>{r['Retorno Absoluto']}</td>
104
- <td>{r['Retorno (%)']}</td>
105
- </tr>
106
- """
107
- tabela_html += "</tbody></table>"
108
-
109
- # Gerar gráfico
110
- img_base64 = gerar_grafico(df, ["Studio", "Franquia", "Ações", "Renda Fixa"])
111
-
112
- analise_final = (f"Após análise dos cenários projetados para {anos} anos, o investimento "
113
- f"<strong>{investimento_mais_valorizado}</strong> apresenta o melhor desempenho, "
114
- f"com um valor final estimado de <strong>{formatar_brl(valor_mais_alto)}</strong>, "
115
- "equivalente a um retorno significativo sobre o capital inicial.")
116
-
117
- comentario_extra = None # Caso queira adicionar algo extra
118
-
119
- return render_template("relatorio.html",
120
- capital=capital,
121
- studio_ret=studio_ret,
122
- valorizacao=valorizacao,
123
- franquia_ret=franquia_ret,
124
- acoes_ret=acoes_ret,
125
- renda_fixa=renda_fixa,
126
- inflacao=inflacao,
127
- anos=anos,
128
- resumo=resumo,
129
- tabela_html=tabela_html,
130
- grafico=img_base64,
131
- analise_final=analise_final,
132
- comentario_extra=comentario_extra,
133
- investimento_mais_valorizado=investimento_mais_valorizado,
134
- valor_mais_alto=valor_mais_alto,
135
- now=datetime.now(),
136
- formatar_brl=formatar_brl)
137
- except Exception as e:
138
- return f"Erro no processamento: {e}"
139
-
140
- # GET: apenas mostra o formulário
141
- return '''
142
- <h2>Simulação de Investimentos</h2>
143
- <form method="post">
144
- <label>Capital Inicial (R$): <input name="capital" type="number" step="0.01" value="100000" required></label><br><br>
145
- <label>Retorno Studio (% ao ano): <input name="studio_ret" type="number" step="0.01" value="8" required></label><br><br>
146
- <label>Valorização Studio (% ao ano): <input name="valorizacao" type="number" step="0.01" value="5" required></label><br><br>
147
- <label>Retorno Franquia (R$ ao ano): <input name="franquia_ret" type="number" step="0.01" value="7000" required></label><br><br>
148
- <label>Retorno Ações (% ao ano): <input name="acoes_ret" type="number" step="0.01" value="10" required></label><br><br>
149
- <label>Retorno Renda Fixa (% ao ano): <input name="renda_fixa" type="number" step="0.01" value="6" required></label><br><br>
150
- <label>Inflação (% ao ano): <input name="inflacao" type="number" step="0.01" value="4" required></label><br><br>
151
- <label>Anos de Projeção: <input name="anos" type="number" value="5" required></label><br><br>
152
- <button type="submit">Gerar Relatório</button>
153
- </form>
154
- '''
155
-
156
- # Página do relatório com template HTML
157
- @app.route("/relatorio")
158
- def relatorio():
159
- # Esta rota só funciona se o formulário for submetido,
160
- # por isso recomendamos usar a rota '/' para gerar o relatório.
161
- return "Acesse a página inicial e preencha o formulário para gerar o relatório."
162
-
163
- # Geração do PDF com WeasyPrint ou pdfkit (exemplo com pdfkit)
164
- from flask import make_response
165
- import pdfkit
166
-
167
- @app.route("/download_pdf", methods=["POST"])
168
- def download_pdf():
169
- try:
170
- # Receber os dados do form para gerar relatório no pdf
171
  capital = float(request.form["capital"])
172
  studio_ret = float(request.form["studio_ret"])
173
  valorizacao = float(request.form["valorizacao"])
@@ -175,135 +56,248 @@ def download_pdf():
175
  acoes_ret = float(request.form["acoes_ret"])
176
  renda_fixa = float(request.form["renda_fixa"])
177
  inflacao = float(request.form["inflacao"])
178
- anos = int(request.form["anos"])
179
-
180
- # Repetir cálculo para gerar dados e gráfico
181
- anos_lista = list(range(0, anos + 1))
182
-
183
- df = pd.DataFrame({"Ano": anos_lista})
184
- df["Studio"] = capital * ((1 + (studio_ret + valorizacao)/100) ** df["Ano"])
185
- df["Franquia"] = capital + franquia_ret * df["Ano"]
186
- df["Ações"] = capital * ((1 + acoes_ret/100) ** df["Ano"])
187
- df["Renda Fixa"] = capital * ((1 + renda_fixa/100) ** df["Ano"])
188
-
189
- valores_finais = df.iloc[-1, 1:]
190
- investimento_mais_valorizado = valores_finais.idxmax()
191
- valor_mais_alto = valores_finais.max()
192
-
193
- resumo = []
194
- for investimento in ["Studio", "Franquia", "Ações", "Renda Fixa"]:
195
- valor_final = valores_finais[investimento]
196
- retorno_abs = valor_final - capital
197
- retorno_pct = (retorno_abs / capital) * 100
198
- resumo.append({
199
- "Investimento": investimento,
200
- "Valor Final": formatar_brl(valor_final),
201
- "Retorno Absoluto": formatar_brl(retorno_abs),
202
- "Retorno (%)": f"{retorno_pct:.2f}%"
203
- })
204
-
205
- tabela_html = """
206
- <table>
207
- <thead>
208
- <tr>
209
- <th style="text-align:left;">Investimento</th>
210
- <th>Valor Final</th>
211
- <th>Retorno Absoluto</th>
212
- <th>Retorno (%)</th>
213
- </tr>
214
- </thead>
215
- <tbody>
216
- """
217
- for r in resumo:
218
- tabela_html += f"""
219
- <tr>
220
- <td style="text-align:left;">{r['Investimento']}</td>
221
- <td>{r['Valor Final']}</td>
222
- <td>{r['Retorno Absoluto']}</td>
223
- <td>{r['Retorno (%)']}</td>
224
- </tr>
225
- """
226
- tabela_html += "</tbody></table>"
227
-
228
- img_base64 = gerar_grafico(df, ["Studio", "Franquia", "Ações", "Renda Fixa"])
229
-
230
- analise_final = (f"Após análise dos cenários projetados para {anos} anos, o investimento "
231
- f"<strong>{investimento_mais_valorizado}</strong> apresenta o melhor desempenho, "
232
- f"com um valor final estimado de <strong>{formatar_brl(valor_mais_alto)}</strong>, "
233
- "equivalente a um retorno significativo sobre o capital inicial.")
234
-
235
- consideracoes_finais = f"""
236
- <h2>Considerações Finais</h2>
237
- <p>{analise_final}</p>
238
- <p>
239
- O investimento que apresentou o maior retorno neste cenário foi o <strong>{investimento_mais_valorizado}</strong>,
240
- atingindo um valor patrimonial final estimado em <strong>{formatar_brl(valor_mais_alto)}</strong>.
241
- </p>
242
- <p>
243
- <strong>Valor Patrimonial</strong> refere-se ao valor total acumulado do investimento, incluindo a valorização do ativo e os rendimentos obtidos ao longo do tempo.
244
- Conforme as normas contábeis e práticas de avaliação de investidores profissionais, o valor patrimonial é fundamental para mensurar a saúde financeira e o crescimento do patrimônio líquido do investidor.
245
- Ele serve como indicador da capacidade do investimento de gerar riqueza real, levando em conta tanto a valorização de mercado quanto a geração de renda.
246
- </p>
247
- """
248
-
249
- html = f"""
250
- <html>
251
- <head>
252
- <meta charset="utf-8">
253
- <style>
254
- body {{ font-family: Arial, sans-serif; font-size: 14px; margin: 20px; }}
255
- h2 {{ color: #2c3e50; }}
256
- table {{ width: 100%; border-collapse: collapse; margin-top: 20px; }}
257
- th, td {{ border: 1px solid #ccc; padding: 6px; text-align: right; }}
258
- th {{ background-color: #f0f0f0; }}
259
- .destaque {{ background: #e8f5e9; padding: 10px; margin-top: 20px; border-left: 6px solid #2e7d32; }}
260
- </style>
261
- </head>
262
- <body>
263
- <h2>Relatório de Simulação de Investimentos</h2>
264
- <p>Data da Simulação: {datetime.today().strftime('%d/%m/%Y')}</p>
265
- <p>Capital Inicial: <strong>{formatar_brl(capital)}</strong></p>
266
-
267
- <h3>Dados de Entrada</h3>
268
- <table>
269
- <tr><th>Parâmetro</th><th>Valor</th></tr>
270
- <tr><td>Retorno Studio (%)</td><td>{studio_ret}%</td></tr>
271
- <tr><td>Valorização Studio (%)</td><td>{valorizacao}%</td></tr>
272
- <tr><td>Retorno Franquia (R$)</td><td>{formatar_brl(franquia_ret)}</td></tr>
273
- <tr><td>Retorno Ações (%)</td><td>{acoes_ret}%</td></tr>
274
- <tr><td>Retorno Renda Fixa (%)</td><td>{renda_fixa}%</td></tr>
275
- <tr><td>Inflação (%)</td><td>{inflacao}%</td></tr>
276
- </table>
277
-
278
- <div class="destaque">{analise_final}</div>
279
-
280
- <img src="data:image/png;base64,{img_base64}" width="100%" />
281
-
282
- <h3>Resumo dos Investimentos</h3>
283
- {tabela_html}
284
-
285
- {consideracoes_finais}
286
- </body>
287
- </html>
288
- """
289
-
290
- # Gerar PDF com pdfkit (você precisa do wkhtmltopdf instalado)
291
- options = {
292
- 'encoding': 'UTF-8',
293
- 'page-size': 'A4',
294
- 'margin-top': '10mm',
295
- 'margin-bottom': '10mm',
296
- 'margin-left': '10mm',
297
- 'margin-right': '10mm',
298
  }
299
- pdf = pdfkit.from_string(html, False, options=options)
300
-
301
- response = make_response(pdf)
302
- response.headers['Content-Type'] = 'application/pdf'
303
- response.headers['Content-Disposition'] = 'attachment; filename=relatorio_investimentos.pdf'
304
- return response
305
- except Exception as e:
306
- return f"Erro na geração do PDF: {e}"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
307
 
308
  if __name__ == '__main__':
309
  app.run(host='0.0.0.0', port=7860, debug=True)
 
4
  os.environ['FONTCONFIG_PATH'] = '/tmp/fontconfig'
5
  os.makedirs('/tmp/fontconfig', exist_ok=True)
6
 
7
+ import os
8
+ os.environ['FONTCONFIG_PATH'] = '/tmp/fontconfig'
9
+ os.makedirs('/tmp/fontconfig', exist_ok=True)
10
 
11
+ from flask import Flask, render_template, request, send_file, make_response
12
  import matplotlib.pyplot as plt
13
+ import pandas as pd
14
  import io
15
  import base64
16
+ from matplotlib.ticker import FuncFormatter
17
+ from xhtml2pdf import pisa
18
  from datetime import datetime
 
19
 
20
  app = Flask(__name__)
21
 
 
22
  def formatar_brl(valor):
23
  return f"R$ {valor:,.2f}".replace(",", "X").replace(".", ",").replace("X", ".")
24
 
25
+ def gerar_analise(investimentos_finais, capital):
26
+ melhor = max(investimentos_finais, key=investimentos_finais.get)
27
+ valor_melhor = investimentos_finais[melhor]
28
+ retorno_pct = ((valor_melhor - capital) / capital) * 100
29
+ analise = f"""
30
+ Após análise dos cenários projetados para 5 anos, o investimento <strong>{melhor}</strong> apresenta o melhor desempenho,
31
+ com um valor final estimado de <strong>{formatar_brl(valor_melhor)}</strong>, equivalente a um retorno de <strong>{retorno_pct:.1f}%</strong>.
32
+ """
33
+ return analise
34
+
35
+ def gerar_consideracoes_finais(investimentos_finais, capital):
36
+ melhor = max(investimentos_finais, key=investimentos_finais.get)
37
+ valor_melhor = investimentos_finais[melhor]
38
+ retorno_pct = ((valor_melhor - capital) / capital) * 100
39
+
40
+ texto = f"""
41
+ <p>Após análise dos cenários projetados para 5 anos, o investimento <strong>{melhor}</strong> apresenta o melhor desempenho,
42
+ com um valor final estimado de <strong>{formatar_brl(valor_melhor)}</strong>, equivalente a um retorno significativo sobre o capital inicial.</p>
43
+ <p><strong>Valor Patrimonial:</strong> corresponde ao valor contábil do investimento, conforme normas contábeis e práticas de investidores profissionais,
44
+ representando o patrimônio acumulado e a valorização dos ativos ao longo do tempo.</p>
45
+ """
46
+ return texto
47
 
 
48
  @app.route("/", methods=["GET", "POST"])
49
  def index():
50
  if request.method == "POST":
51
+ # Captura os dados do formulário
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  capital = float(request.form["capital"])
53
  studio_ret = float(request.form["studio_ret"])
54
  valorizacao = float(request.form["valorizacao"])
 
56
  acoes_ret = float(request.form["acoes_ret"])
57
  renda_fixa = float(request.form["renda_fixa"])
58
  inflacao = float(request.form["inflacao"])
59
+
60
+ anos = list(range(1, 6))
61
+
62
+ # Calcula evolução Studio
63
+ patrimonio_studio = [capital * ((1 + valorizacao / 100) ** ano) for ano in anos]
64
+ renda_acumulada_studio = [capital * (((1 + studio_ret / 100) ** (12 * ano)) - 1) for ano in anos]
65
+ studio_total = [p + r for p, r in zip(patrimonio_studio, renda_acumulada_studio)]
66
+
67
+ # Outras opções
68
+ franquia = [capital + (franquia_ret * ano) for ano in anos]
69
+ acoes = [capital * ((1 + acoes_ret / 100) ** ano) for ano in anos]
70
+ renda_fixa_valores = [capital * ((1 + renda_fixa / 100) ** ano) for ano in anos]
71
+
72
+ # Monta dataframe para tabela e relatório
73
+ dados = {
74
+ "Ano": anos,
75
+ "Studio (Patrimônio + Renda)": studio_total,
76
+ "Franquia": franquia,
77
+ "Ações": acoes,
78
+ "Renda Fixa": renda_fixa_valores
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  }
80
+ df = pd.DataFrame(dados)
81
+
82
+ investimentos_finais = {
83
+ "Studio": studio_total[-1],
84
+ "Franquia": franquia[-1],
85
+ "Ações": acoes[-1],
86
+ "Renda Fixa": renda_fixa_valores[-1],
87
+ }
88
+
89
+ investimento_mais_valorizado = max(investimentos_finais, key=investimentos_finais.get)
90
+ valor_mais_alto = investimentos_finais[investimento_mais_valorizado]
91
+
92
+ # Formatar dataframe para exibir valores em BRL
93
+ df_formatado = df.copy()
94
+ for col in df.columns:
95
+ if col != "Ano":
96
+ df_formatado[col] = df_formatado[col].apply(formatar_brl)
97
+
98
+ tabela_html = df_formatado.to_html(index=False, classes="table table-striped table-sm", border=0)
99
+
100
+ analise_final = gerar_analise(investimentos_finais, capital)
101
+ consideracoes = gerar_consideracoes_finais(investimentos_finais, capital)
102
+
103
+ # Gerar gráfico base64 para exibir na página HTML
104
+ plt.figure(figsize=(8, 5))
105
+ plt.plot(anos, studio_total, label="Studio (Patrimônio + Renda)", marker="o")
106
+ plt.plot(anos, franquia, label="Franquia", marker="o")
107
+ plt.plot(anos, acoes, label="Ações", marker="o")
108
+ plt.plot(anos, renda_fixa_valores, label="Renda Fixa", marker="o")
109
+ plt.title("Projeção de Investimentos")
110
+ plt.xlabel("Ano")
111
+ plt.ylabel("Valor (R$)")
112
+ plt.legend()
113
+ plt.grid(True)
114
+ plt.gca().yaxis.set_major_formatter(FuncFormatter(lambda x, _: f"R${x:,.0f}".replace(",", ".")))
115
+ plt.tight_layout()
116
+ buf = io.BytesIO()
117
+ plt.savefig(buf, format="png")
118
+ buf.seek(0)
119
+ grafico_base64 = base64.b64encode(buf.getvalue()).decode("utf-8")
120
+ buf.close()
121
+ plt.close()
122
+
123
+ return render_template(
124
+ "index.html",
125
+ capital=capital,
126
+ studio_ret=studio_ret,
127
+ valorizacao=valorizacao,
128
+ franquia_ret=franquia_ret,
129
+ acoes_ret=acoes_ret,
130
+ renda_fixa=renda_fixa,
131
+ inflacao=inflacao,
132
+ anos=anos,
133
+ tabela=tabela_html,
134
+ grafico=grafico_base64,
135
+ analise_final=analise_final,
136
+ consideracoes=consideracoes,
137
+ investimento_mais_valorizado=investimento_mais_valorizado,
138
+ valor_mais_alto=valor_mais_alto
139
+ )
140
+
141
+ return render_template("index.html")
142
+
143
+
144
+ @app.route("/download_pdf", methods=["POST"])
145
+ def download_pdf():
146
+ capital = float(request.form["capital"])
147
+ studio_ret = float(request.form["studio_ret"])
148
+ valorizacao = float(request.form["valorizacao"])
149
+ franquia_ret = float(request.form["franquia_ret"])
150
+ acoes_ret = float(request.form["acoes_ret"])
151
+ renda_fixa = float(request.form["renda_fixa"])
152
+ inflacao = float(request.form["inflacao"])
153
+
154
+ anos = list(range(1, 6))
155
+
156
+ patrimonio_studio = [capital * ((1 + valorizacao / 100) ** ano) for ano in anos]
157
+ renda_acumulada_studio = [capital * (((1 + studio_ret / 100) ** (12 * ano)) - 1) for ano in anos]
158
+ studio_total = [p + r for p, r in zip(patrimonio_studio, renda_acumulada_studio)]
159
+
160
+ franquia = [capital + (franquia_ret * ano) for ano in anos]
161
+ acoes = [capital * ((1 + acoes_ret / 100) ** ano) for ano in anos]
162
+ renda_fixa_valores = [capital * ((1 + renda_fixa / 100) ** ano) for ano in anos]
163
+
164
+ dados = {
165
+ "Ano": anos,
166
+ "Studio (Patrimônio + Renda)": studio_total,
167
+ "Franquia": franquia,
168
+ "Ações": acoes,
169
+ "Renda Fixa": renda_fixa_valores
170
+ }
171
+ df = pd.DataFrame(dados)
172
+
173
+ investimentos_finais = {
174
+ "Studio": studio_total[-1],
175
+ "Franquia": franquia[-1],
176
+ "Ações": acoes[-1],
177
+ "Renda Fixa": renda_fixa_valores[-1],
178
+ }
179
+ investimento_mais_valorizado = max(investimentos_finais, key=investimentos_finais.get)
180
+ valor_mais_alto = investimentos_finais[investimento_mais_valorizado]
181
+
182
+ # Gerar gráfico PNG
183
+ plt.figure(figsize=(8, 5))
184
+ plt.plot(anos, studio_total, label="Studio (Patrimônio + Renda)", marker="o")
185
+ plt.plot(anos, franquia, label="Franquia", marker="o")
186
+ plt.plot(anos, acoes, label="Ações", marker="o")
187
+ plt.plot(anos, renda_fixa_valores, label="Renda Fixa", marker="o")
188
+ plt.title("Projeção de Investimentos (5 anos)")
189
+ plt.xlabel("Ano")
190
+ plt.ylabel("Valor (R$)")
191
+ plt.legend()
192
+ plt.grid(True)
193
+ plt.gca().yaxis.set_major_formatter(FuncFormatter(lambda x, _: f"R${x:,.0f}".replace(",", ".")))
194
+ plt.tight_layout()
195
+
196
+ img_buf = io.BytesIO()
197
+ plt.savefig(img_buf, format='png')
198
+ img_buf.seek(0)
199
+ img_base64 = base64.b64encode(img_buf.getvalue()).decode("utf-8")
200
+ img_buf.close()
201
+ plt.close()
202
+
203
+ # Formatar dataframe para relatório PDF (com tabela)
204
+ df_formatado = df.copy()
205
+ for col in df.columns:
206
+ if col != "Ano":
207
+ df_formatado[col] = df_formatado[col].apply(formatar_brl)
208
+
209
+ tabela_html = df_formatado.to_html(index=False, border=1, classes="table")
210
+
211
+ analise = gerar_analise(investimentos_finais, capital)
212
+ consideracoes = gerar_consideracoes_finais(investimentos_finais, capital)
213
+
214
+ html = f"""
215
+ <html>
216
+ <head>
217
+ <meta charset="utf-8" />
218
+ <style>
219
+ body {{
220
+ font-family: Arial, sans-serif;
221
+ margin: 40px;
222
+ font-size: 12pt;
223
+ color: #333;
224
+ }}
225
+ h1 {{
226
+ text-align: center;
227
+ color: #2c3e50;
228
+ }}
229
+ h2 {{
230
+ color: #2c3e50;
231
+ border-bottom: 1px solid #ccc;
232
+ padding-bottom: 5px;
233
+ }}
234
+ p {{
235
+ text-align: justify;
236
+ line-height: 1.4;
237
+ }}
238
+ .analise {{
239
+ background: #e8f5e9;
240
+ border-left: 6px solid #2e7d32;
241
+ padding: 10px;
242
+ margin: 15px 0;
243
+ font-size: 11pt;
244
+ }}
245
+ img {{
246
+ display: block;
247
+ margin: 20px auto;
248
+ max-width: 100%;
249
+ height: auto;
250
+ }}
251
+ table {{
252
+ width: 100%;
253
+ border-collapse: collapse;
254
+ margin-top: 20px;
255
+ font-size: 11pt;
256
+ }}
257
+ th, td {{
258
+ border: 1px solid #ccc;
259
+ padding: 8px;
260
+ text-align: right;
261
+ }}
262
+ th {{
263
+ background-color: #f0f0f0;
264
+ color: #2c3e50;
265
+ }}
266
+ th:first-child, td:first-child {{
267
+ text-align: center;
268
+ }}
269
+ </style>
270
+ </head>
271
+ <body>
272
+ <h1>Relatório de Simulação de Investimentos</h1>
273
+ <p><strong>Data da Simulação:</strong> {datetime.today().strftime('%d/%m/%Y')}</p>
274
+ <p><strong>Capital Inicial:</strong> {formatar_brl(capital)}</p>
275
+
276
+ <div class="analise">{analise}</div>
277
+ <div class="analise">{consideracoes}</div>
278
+
279
+ <h2>Gráfico de Evolução dos Investimentos</h2>
280
+ <img src="data:image/png;base64,{img_base64}" alt="Gráfico de Investimentos" />
281
+
282
+ <h2>Evolução Ano a Ano</h2>
283
+ {tabela_html}
284
+ </body>
285
+ </html>
286
+ """
287
+
288
+ pdf_buffer = io.BytesIO()
289
+ pisa_status = pisa.CreatePDF(io.StringIO(html), dest=pdf_buffer)
290
+ if pisa_status.err:
291
+ return "Erro ao gerar PDF", 500
292
+
293
+ pdf_buffer.seek(0)
294
+ return send_file(
295
+ pdf_buffer,
296
+ mimetype="application/pdf",
297
+ as_attachment=True,
298
+ download_name="relatorio_investimentos.pdf"
299
+ )
300
+
301
 
302
  if __name__ == '__main__':
303
  app.run(host='0.0.0.0', port=7860, debug=True)