Update app.py
Browse files
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 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
25 |
-
|
26 |
-
|
27 |
-
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
|
34 |
-
|
35 |
-
|
36 |
-
|
37 |
-
|
38 |
-
|
|
|
|
|
|
|
|
|
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 |
-
|
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 |
-
|
179 |
-
|
180 |
-
|
181 |
-
|
182 |
-
|
183 |
-
|
184 |
-
|
185 |
-
|
186 |
-
|
187 |
-
|
188 |
-
|
189 |
-
|
190 |
-
|
191 |
-
|
192 |
-
|
193 |
-
|
194 |
-
|
195 |
-
|
196 |
-
|
197 |
-
|
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 |
-
|
300 |
-
|
301 |
-
|
302 |
-
|
303 |
-
|
304 |
-
|
305 |
-
|
306 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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)
|