Persano commited on
Commit
1e783cb
·
verified ·
1 Parent(s): ea50e28

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +231 -0
app.py ADDED
@@ -0,0 +1,231 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import io
3
+ import base64
4
+ import pandas as pd
5
+ import matplotlib.pyplot as plt
6
+ from flask import Flask, render_template, request, send_file
7
+ from matplotlib.ticker import FuncFormatter
8
+ from xhtml2pdf import pisa
9
+ from datetime import datetime
10
+ import openai
11
+ import re
12
+
13
+ app = Flask(__name__)
14
+
15
+ openai.api_key = os.getenv("OPENAI_API_KEY")
16
+
17
+ def formatar_brl(valor):
18
+ return f"R$ {valor:,.2f}".replace(",", "X").replace(".", ",").replace("X", ".")
19
+
20
+ def formatar_texto_analise(texto):
21
+ # Quebra linhas e cria parágrafos, destacando palavras/chaves importantes
22
+ paragrafos = texto.strip().split('\n')
23
+ paragrafos_html = []
24
+ for p in paragrafos:
25
+ p = p.strip()
26
+ if not p:
27
+ continue
28
+ # Destacar palavras ou números importantes (melhor investimento, retorno, percentual, valores em R$)
29
+ p = re.sub(r'(melhor investimento|retorno|percentual|R\$ [\d\.,]+|destaca|investimento|percentual)', r'<strong>\1</strong>', p, flags=re.I)
30
+ paragrafos_html.append(f'<p>{p}</p>')
31
+ return '\n'.join(paragrafos_html)
32
+
33
+ def gerar_analise(investimentos_finais, capital, patrimonio_studio_final):
34
+ melhor = max(investimentos_finais, key=investimentos_finais.get)
35
+ valor_melhor = investimentos_finais[melhor]
36
+ retorno_pct = ((valor_melhor - capital) / capital) * 100
37
+ texto = f"""
38
+ Após análise dos cenários projetados para 5 anos, o investimento <strong>{melhor}</strong> apresenta o melhor desempenho,
39
+ com um valor final estimado de <strong>{formatar_brl(valor_melhor)}</strong>, equivalente a um retorno de <strong>{retorno_pct:.1f}%</strong>.
40
+ <br><br>
41
+ O valor patrimonial do Studio, conforme normas contábeis e profissionais de investimento, representa o valor acumulado do imóvel sem considerar a renda gerada,
42
+ ou seja, é o aumento do patrimônio bruto estimado. Neste cenário, o valor patrimonial final do Studio é <strong>{formatar_brl(patrimonio_studio_final)}</strong>.
43
+ """
44
+ return texto
45
+
46
+ def gerar_analise_ia(investimentos_finais, capital, patrimonio_studio_final):
47
+ prompt = f"""
48
+ Faça uma análise profissional e detalhada em linguagem clara e acessível sobre os seguintes dados financeiros:
49
+ - Capital inicial: R$ {capital:,.2f}
50
+ - Valor patrimonial final do Studio: R$ {patrimonio_studio_final:,.2f}
51
+ - Investimentos finais após 5 anos:
52
+ """
53
+ for nome, valor in investimentos_finais.items():
54
+ prompt += f" - {nome}: R$ {valor:,.2f}\n"
55
+
56
+ prompt += """
57
+ Destaque qual foi o melhor investimento, o retorno percentual sobre o capital, e comente sobre possíveis estratégias e perfis de risco. Seja objetivo, claro e com tom consultivo.
58
+ """
59
+
60
+ resposta = openai.ChatCompletion.create(
61
+ model="gpt-4o",
62
+ messages=[
63
+ {"role": "system", "content": "Você é um analista financeiro experiente."},
64
+ {"role": "user", "content": prompt}
65
+ ]
66
+ )
67
+ return resposta.choices[0].message.content
68
+
69
+ def render_pdf(template_src, context_dict):
70
+ html = render_template(template_src, **context_dict)
71
+ result = io.BytesIO()
72
+ pisa_status = pisa.CreatePDF(io.StringIO(html), dest=result)
73
+ if not pisa_status.err:
74
+ result.seek(0)
75
+ return result
76
+ return None
77
+
78
+ @app.route("/", methods=["GET", "POST"])
79
+ def index():
80
+ if request.method == "POST":
81
+ capital = float(request.form["capital"])
82
+ studio_ret = float(request.form["studio_ret"])
83
+ valorizacao = float(request.form["valorizacao"])
84
+ franquia_ret = float(request.form["franquia_ret"])
85
+ acoes_ret = float(request.form["acoes_ret"])
86
+ renda_fixa = float(request.form["renda_fixa"])
87
+ inflacao = float(request.form["inflacao"])
88
+
89
+ anos = list(range(1, 6))
90
+
91
+ patrimonio_studio = [capital * ((1 + valorizacao / 100) ** ano) for ano in anos]
92
+ renda_acumulada_studio = [capital * (((1 + studio_ret / 100) ** (12 * ano)) - 1) for ano in anos]
93
+ studio_total = [p + r for p, r in zip(patrimonio_studio, renda_acumulada_studio)]
94
+
95
+ franquia = [capital + (franquia_ret * ano) for ano in anos]
96
+ acoes = [capital * ((1 + acoes_ret / 100) ** ano) for ano in anos]
97
+ renda_fixa_valores = [capital * ((1 + renda_fixa / 100) ** ano) for ano in anos]
98
+
99
+ dados = {
100
+ "Ano": anos,
101
+ "Studio (Patrimônio + Renda)": studio_total,
102
+ "Franquia": franquia,
103
+ "Ações": acoes,
104
+ "Renda Fixa": renda_fixa_valores
105
+ }
106
+ df = pd.DataFrame(dados)
107
+
108
+ investimentos_finais = {
109
+ "Studio": studio_total[-1],
110
+ "Franquia": franquia[-1],
111
+ "Ações": acoes[-1],
112
+ "Renda Fixa": renda_fixa_valores[-1],
113
+ }
114
+
115
+ plt.figure(figsize=(8, 5))
116
+ plt.plot(anos, studio_total, label="Studio (Patrimônio + Renda)", marker="o")
117
+ plt.plot(anos, franquia, label="Franquia", marker="o")
118
+ plt.plot(anos, acoes, label="Ações", marker="o")
119
+ plt.plot(anos, renda_fixa_valores, label="Renda Fixa", marker="o")
120
+ plt.title("Projeção de Investimentos (5 anos)")
121
+ plt.xlabel("Ano")
122
+ plt.ylabel("Valor (R$)")
123
+ plt.legend()
124
+ plt.grid(True)
125
+ plt.gca().yaxis.set_major_formatter(FuncFormatter(lambda x, _: f"R${x:,.0f}".replace(",", ".")))
126
+ plt.tight_layout()
127
+
128
+ buf = io.BytesIO()
129
+ plt.savefig(buf, format="png")
130
+ buf.seek(0)
131
+ grafico_base64 = base64.b64encode(buf.getvalue()).decode("utf-8")
132
+ buf.close()
133
+ plt.close()
134
+
135
+ df_formatado = df.copy()
136
+ for col in df.columns:
137
+ if col != "Ano":
138
+ df_formatado[col] = df_formatado[col].apply(formatar_brl)
139
+ tabela = df_formatado.to_html(index=False, classes="table table-striped table-sm text-end", border=0)
140
+
141
+ texto_bruto = gerar_analise_ia(investimentos_finais, capital, patrimonio_studio[-1])
142
+ analise_final = formatar_texto_analise(texto_bruto)
143
+
144
+ return render_template(
145
+ "index.html",
146
+ capital=capital,
147
+ tabela=tabela,
148
+ grafico=grafico_base64,
149
+ analise_final=analise_final
150
+ )
151
+
152
+ return render_template("index.html")
153
+
154
+ @app.route("/gerar-pdf", methods=["POST"])
155
+ def gerar_pdf():
156
+ capital = float(request.form["capital"])
157
+ studio_ret = float(request.form["studio_ret"])
158
+ valorizacao = float(request.form["valorizacao"])
159
+ franquia_ret = float(request.form["franquia_ret"])
160
+ acoes_ret = float(request.form["acoes_ret"])
161
+ renda_fixa = float(request.form["renda_fixa"])
162
+ inflacao = float(request.form["inflacao"])
163
+
164
+ anos = list(range(1, 6))
165
+
166
+ patrimonio_studio = [capital * ((1 + valorizacao / 100) ** ano) for ano in anos]
167
+ renda_acumulada_studio = [capital * (((1 + studio_ret / 100) ** (12 * ano)) - 1) for ano in anos]
168
+ studio_total = [p + r for p, r in zip(patrimonio_studio, renda_acumulada_studio)]
169
+ franquia = [capital + (franquia_ret * ano) for ano in anos]
170
+ acoes = [capital * ((1 + acoes_ret / 100) ** ano) for ano in anos]
171
+ renda_fixa_valores = [capital * ((1 + renda_fixa / 100) ** ano) for ano in anos]
172
+
173
+ dados = {
174
+ "Ano": anos,
175
+ "Studio (Patrimônio + Renda)": studio_total,
176
+ "Franquia": franquia,
177
+ "Ações": acoes,
178
+ "Renda Fixa": renda_fixa_valores
179
+ }
180
+ df = pd.DataFrame(dados)
181
+
182
+ investimentos_finais = {
183
+ "Studio": studio_total[-1],
184
+ "Franquia": franquia[-1],
185
+ "Ações": acoes[-1],
186
+ "Renda Fixa": renda_fixa_valores[-1],
187
+ }
188
+
189
+ buf = io.BytesIO()
190
+ plt.figure(figsize=(8, 5))
191
+ plt.plot(anos, studio_total, label="Studio (Patrimônio + Renda)", marker="o")
192
+ plt.plot(anos, franquia, label="Franquia", marker="o")
193
+ plt.plot(anos, acoes, label="Ações", marker="o")
194
+ plt.plot(anos, renda_fixa_valores, label="Renda Fixa", marker="o")
195
+ plt.title("Projeção de Investimentos (5 anos)")
196
+ plt.xlabel("Ano")
197
+ plt.ylabel("Valor (R$)")
198
+ plt.legend()
199
+ plt.grid(True)
200
+ plt.tight_layout()
201
+ plt.savefig(buf, format="png")
202
+ buf.seek(0)
203
+ grafico_base64 = base64.b64encode(buf.read()).decode("utf-8")
204
+ buf.close()
205
+ plt.close()
206
+
207
+ df_formatado = df.copy()
208
+ for col in df.columns:
209
+ if col != "Ano":
210
+ df_formatado[col] = df_formatado[col].apply(formatar_brl)
211
+ tabela_html = df_formatado.to_html(index=False, classes="tabela", border=0)
212
+
213
+ texto_bruto = gerar_analise_ia(investimentos_finais, capital, patrimonio_studio[-1])
214
+ analise_final_ia = formatar_texto_analise(texto_bruto)
215
+
216
+ context = {
217
+ "capital": capital,
218
+ "grafico": grafico_base64,
219
+ "tabela": tabela_html,
220
+ "analise_final": analise_final_ia,
221
+ "data_hoje": datetime.now().strftime("São Paulo, %d de %B de %Y")
222
+ }
223
+
224
+ pdf = render_pdf("relatorio.html", context)
225
+ if pdf:
226
+ return send_file(pdf, mimetype="application/pdf", as_attachment=True, download_name="relatorio_investimento.pdf")
227
+ else:
228
+ return "Erro ao gerar PDF", 500
229
+
230
+ if __name__ == "__main__":
231
+ app.run(host="0.0.0.0", port=int(os.environ.get("PORT", 7860)))