fschwartzer commited on
Commit
553f384
·
verified ·
1 Parent(s): 052864d

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +233 -0
app.py ADDED
@@ -0,0 +1,233 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import os
3
+ from datetime import date
4
+ import io
5
+ from reportlab.platypus import (
6
+ BaseDocTemplate, PageTemplate, Frame, Paragraph, Spacer,
7
+ Table, TableStyle, PageBreak
8
+ )
9
+ from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
10
+ from reportlab.lib.pagesizes import A4
11
+ from reportlab.lib import colors
12
+ from reportlab.lib.units import cm
13
+ from reportlab.lib.enums import TA_CENTER, TA_JUSTIFY, TA_LEFT, TA_RIGHT
14
+
15
+ # =================================================================================
16
+ # FUNÇÃO DE GERAÇÃO DE PDF (MODIFICADA PARA ACEITAR DADOS E RETORNAR BYTES)
17
+ # =================================================================================
18
+ def create_pdf_report(user_data):
19
+ """
20
+ Gera o relatório em PDF em memória, preenchido com os dados do usuário.
21
+ """
22
+ buffer = io.BytesIO()
23
+ doc = BaseDocTemplate(buffer, pagesize=A4)
24
+
25
+ HEADER_HEIGHT = 3.5 * cm
26
+ main_frame = Frame(
27
+ doc.leftMargin,
28
+ doc.bottomMargin,
29
+ doc.width,
30
+ doc.height - HEADER_HEIGHT,
31
+ id='main_frame'
32
+ )
33
+
34
+ def header(canvas, doc):
35
+ canvas.saveState()
36
+ page_width = doc.width + doc.leftMargin + doc.rightMargin
37
+
38
+ # Logos (mantenha a lógica de verificar se existem)
39
+ if os.path.exists('logo_pref.png'):
40
+ canvas.drawImage('logo_pref.png', doc.leftMargin, 740, width=4*cm, preserveAspectRatio=True, mask='auto')
41
+ if os.path.exists('logo_receita.png'):
42
+ logo_width = 3.5 * cm
43
+ x_centered = (page_width - logo_width) / 2
44
+ canvas.drawImage('logo_receita.png', x_centered, 740, width=logo_width, preserveAspectRatio=True, mask='auto')
45
+
46
+ header_style = ParagraphStyle(name='HeaderStyle', fontSize=8, alignment=TA_RIGHT)
47
+ p = Paragraph("<b>DAI-ESJL</b><br/>Divisão de Avaliação de Imóveis<br/>Equipe de Suporte, Judiciais e Locações", header_style)
48
+ p.wrapOn(canvas, doc.width, doc.topMargin)
49
+ p.drawOn(canvas, doc.leftMargin, 757.5)
50
+
51
+ # PROCESSO com número do usuário
52
+ processo_style = ParagraphStyle(name='ProcessoStyle', fontSize=10, alignment=TA_RIGHT, textColor=colors.black)
53
+ p_proc = Paragraph(f"PROCESSO {user_data['processo_numero']}", processo_style)
54
+ p_proc.wrapOn(canvas, doc.width, 1*cm)
55
+ p_proc.drawOn(canvas, doc.leftMargin, 730)
56
+
57
+ canvas.restoreState()
58
+
59
+ def footer(canvas, doc):
60
+ canvas.saveState()
61
+ canvas.setFont('Helvetica', 9)
62
+ canvas.drawRightString(A4[0] - doc.rightMargin, doc.bottomMargin - 0.5*cm, str(doc.page))
63
+ canvas.restoreState()
64
+
65
+ doc.addPageTemplates([PageTemplate(id='main', frames=main_frame, onPage=header, onPageEnd=footer)])
66
+
67
+ styles = getSampleStyleSheet()
68
+ styles.add(ParagraphStyle(name='Justify', alignment=TA_JUSTIFY, fontSize=10, leading=14))
69
+ styles.add(ParagraphStyle(name='Center', alignment=TA_CENTER, fontSize=10, leading=14))
70
+ styles.add(ParagraphStyle(name='MainTitle', fontSize=12, fontName='Helvetica-Bold', alignment=TA_CENTER, textColor=colors.black, borderPadding=(5, 2, 5, 2)))
71
+ styles.add(ParagraphStyle(name='SectionTitle', fontSize=10, fontName='Helvetica-Bold', spaceBefore=16, spaceAfter=6))
72
+ styles.add(ParagraphStyle(name='TableLabel', fontName='Helvetica-Bold', fontSize=9, alignment=TA_LEFT))
73
+ styles.add(ParagraphStyle(name='TableContent', fontSize=9, alignment=TA_LEFT, leading=11))
74
+
75
+ def create_styled_table(data, col_widths):
76
+ styled_data = []
77
+ for row_idx, row in enumerate(data):
78
+ styled_row = []
79
+ for col_idx, cell_content in enumerate(row):
80
+ # O conteúdo da segunda coluna é tratado como 'TableContent'
81
+ style = styles['TableLabel'] if col_idx == 0 else styles['TableContent']
82
+ styled_row.append(Paragraph(str(cell_content), style))
83
+ styled_data.append(styled_row)
84
+ tbl = Table(styled_data, colWidths=col_widths)
85
+ tbl.setStyle(TableStyle([
86
+ ('VALIGN', (0, 0), (-1, -1), 'TOP'),
87
+ ('GRID', (0, 0), (-1, -1), 0.5, colors.grey),
88
+ ('LEFTPADDING', (0, 0), (-1, -1), 6), ('RIGHTPADDING', (0, 0), (-1, -1), 6),
89
+ ('TOPPADDING', (0, 0), (-1, -1), 4), ('BOTTOMPADDING', (0, 0), (-1, -1), 4),
90
+ ]))
91
+ return tbl
92
+
93
+ story = []
94
+
95
+ # --- PÁGINA 1 ---
96
+ story.append(Spacer(1, 0.5 * cm))
97
+ # Título com número do usuário
98
+ story.append(Paragraph(f"INFORMAÇÃO TÉCNICA<br/>IT_{user_data['it_numero']}", styles['MainTitle']))
99
+
100
+ story.append(Paragraph("• SOLICITAÇÃO", styles['SectionTitle']))
101
+ solicitacao_data = [
102
+ ['Unidade demandante:', user_data['unidade_demandante']],
103
+ ['Finalidade da Avaliação:', user_data['finalidade_avaliacao']]
104
+ ]
105
+ story.append(create_styled_table(solicitacao_data, col_widths=[4.5*cm, '*']))
106
+
107
+ story.append(Paragraph("• IMÓVEL OBJETO", styles['SectionTitle']))
108
+ imovel_data = [
109
+ ['Endereço - SMF:', user_data['endereco_smf']],
110
+ ['Bairro (Setor/Quarteirão) - SMF:', user_data['bairro_smf']],
111
+ ['Lote Fiscal / Inscrição - SMF:', user_data['lote_fiscal']],
112
+ ['Registro imóvel nº - SMF:', user_data['registro_imovel']],
113
+ ['Finalidade Imóvel - SMF:', user_data['finalidade_imovel']],
114
+ ['Área Territorial - SMF:', user_data['area_territorial']],
115
+ ['Área construída – SMF:', user_data['area_construida']],
116
+ ['Exercícios em análise:', user_data['exercicios_analise']],
117
+ ['Valores Venais Guias IPTU (Exercícios):', user_data['valores_venais']]
118
+ ]
119
+ story.append(create_styled_table(imovel_data, col_widths=[4.5*cm, '*']))
120
+ story.append(PageBreak())
121
+
122
+ # --- PÁGINA 2 ---
123
+ story.append(Paragraph("• ANÁLISE TÉCNICA PRELIMINAR", styles['SectionTitle']))
124
+ analise_data = [
125
+ ['Unidade responsável:', user_data['unidade_responsavel']],
126
+ ['Técnico responsável:', user_data['tecnico_responsavel']],
127
+ ['Método de Avaliação (ABNT NBR 14.653-2):', user_data['metodo_avaliacao']]
128
+ ]
129
+ story.append(create_styled_table(analise_data, col_widths=[4.5*cm, '*']))
130
+
131
+ story.append(Paragraph("• CONCLUSÃO TÉCNICA", styles['SectionTitle']))
132
+ conclusao_data = [
133
+ ['Características particularmente<br/>desvalorizantes:', user_data['caracteristicas_desvalorizantes']],
134
+ ['Conclusão:', user_data['conclusao_preliminar']]
135
+ ]
136
+ story.append(create_styled_table(conclusao_data, col_widths=[6*cm, '*']))
137
+ story.append(PageBreak())
138
+
139
+ # --- PÁGINAS SEGUINTES (CONTEÚDO TEXTUAL) ---
140
+ story.append(Paragraph("1. CONSIDERAÇÕES INICIAIS", styles['SectionTitle']))
141
+ story.append(Paragraph(user_data['texto_consideracoes'], styles['Justify']))
142
+
143
+ story.append(Paragraph("2. ANÁLISE TÉCNICA PRELIMINAR", styles['SectionTitle']))
144
+ story.append(Paragraph(user_data['texto_analise'], styles['Justify']))
145
+
146
+ # ... Adicione os outros parágrafos da mesma forma ...
147
+
148
+ story.append(Spacer(1, 3*cm))
149
+
150
+ # Data automática
151
+ today = date.today()
152
+ meses = ("janeiro", "fevereiro", "março", "abril", "maio", "junho", "julho", "agosto", "setembro", "outubro", "novembro", "dezembro")
153
+ data_formatada = f"Porto Alegre, {today.day} de {meses[today.month - 1]} de {today.year}."
154
+ story.append(Paragraph(data_formatada, styles['Center']))
155
+
156
+ doc.build(story)
157
+
158
+ # Retorna os bytes do PDF gerado
159
+ pdf_bytes = buffer.getvalue()
160
+ buffer.close()
161
+ return pdf_bytes
162
+
163
+ # =================================================================================
164
+ # INTERFACE DO STREAMLIT
165
+ # =================================================================================
166
+ st.set_page_config(layout="wide")
167
+ st.title("Gerador de Relatório Técnico")
168
+
169
+ # Coletando os dados do usuário em colunas para melhor organização
170
+ col1, col2 = st.columns(2)
171
+
172
+ with col1:
173
+ st.header("Dados Gerais e de Capa")
174
+ user_data = {}
175
+ user_data['processo_numero'] = st.text_input("Número do Processo:", "SEI-...")
176
+ user_data['it_numero'] = st.text_input("Número da Informação Técnica (ex: 001/2025):", "XXX/2025")
177
+
178
+ st.subheader("Solicitação (Página 1)")
179
+ user_data['unidade_demandante'] = st.text_input("Unidade demandante:", "Equipe da Planta Genérica de Valores - EPGV (DAI/RM/SMF)")
180
+ user_data['finalidade_avaliacao'] = st.text_input("Finalidade da Avaliação:", "Análise Técnica Preliminar - Finalidade Conforme Demanda EPGV")
181
+
182
+ st.subheader("Imóvel Objeto (Página 1)")
183
+ user_data['endereco_smf'] = st.text_input("Endereço - SMF:")
184
+ user_data['bairro_smf'] = st.text_input("Bairro (Setor/Quarteirão) - SMF:")
185
+ user_data['lote_fiscal'] = st.text_input("Lote Fiscal / Inscrição - SMF:")
186
+ user_data['registro_imovel'] = st.text_input("Registro imóvel nº - SMF:", "Matrícula xxxxx / yª Zona de Porto Alegre")
187
+ user_data['finalidade_imovel'] = st.text_area("Finalidade Imóvel - SMF:", "Opção A: 10-Terreno\nOpção B: 20 - Residência Isolada", height=100)
188
+ user_data['area_territorial'] = st.text_input("Área Territorial - SMF:", "0,00 m² (privativa) / 0,00 m² (total)")
189
+ user_data['area_construida'] = st.text_area("Área construída – SMF:", "00,00m² / YYYY / 35-ALVENARIA (C) - CASAS ATE 2 PAVIM.\n00,00m² / YYYY / 35-ALVENARIA (C) - CASAS ATE 2 PAVIM.", height=100)
190
+ user_data['exercicios_analise'] = st.text_area("Exercícios em análise:", "XXXX a YYYY (não há lançamentos anteriores a XXXX)", height=150)
191
+ user_data['valores_venais'] = st.text_input("Valores Venais Guias IPTU (Exercícios):")
192
+
193
+ with col2:
194
+ st.header("Análise e Conclusão (Página 2)")
195
+ user_data['unidade_responsavel'] = st.text_input("Unidade responsável:", "Equipe de Suporte, Judiciais e Locações - ESJL (DAI/RM/SMF)")
196
+ user_data['tecnico_responsavel'] = st.text_input("Técnico responsável:")
197
+ user_data['metodo_avaliacao'] = st.text_area("Método de Avaliação (ABNT NBR 14.653-2):", "Opção A: Método Comparativo de Dados de Mercado\nOpção B:\n- Método Comparativo de Dados de Mercado\n- Método de Quantificação de Custo", height=150)
198
+ user_data['caracteristicas_desvalorizantes'] = st.text_input("Características particularmente desvalorizantes:")
199
+ user_data['conclusao_preliminar'] = st.text_area("Conclusão:", "Opção A: Requer análise técnica pormenorizada\n\nOpção B: Não requer análise técnica pormenorizada.\n\nOpção C: Sugerida análise fiscal quanto a ocorrência de característica particularmente desvalorizante prevista na Legislação.", height=200)
200
+
201
+ st.header("Corpo do Relatório (Textos Longos)")
202
+ user_data['texto_consideracoes'] = st.text_area(
203
+ "1. CONSIDERAÇÕES INICIAIS",
204
+ "A presente Informação Técnica foi elaborada por esta Equipe de Suporte, Judiciais e Locações (ESJL)...",
205
+ height=200
206
+ )
207
+ user_data['texto_analise'] = st.text_area(
208
+ "2. ANÁLISE TÉCNICA PRELIMINAR",
209
+ "Para garantir o embasamento técnico desta análise preliminar...",
210
+ height=200
211
+ )
212
+ # Adicione mais st.text_area para cada parágrafo longo que você precisa editar
213
+
214
+ st.markdown("---")
215
+
216
+ if st.button("Gerar Relatório em PDF"):
217
+ with st.spinner("Gerando PDF..."):
218
+ # Chamar a função para gerar o PDF em memória
219
+ pdf_bytes = create_pdf_report(user_data)
220
+
221
+ # Armazenar os bytes do PDF no estado da sessão para o download
222
+ st.session_state.pdf_bytes = pdf_bytes
223
+ st.session_state.file_name = f"IT_{user_data['it_numero'].replace('/', '_')}.pdf"
224
+
225
+ # Botão de download só aparece se o PDF foi gerado
226
+ if 'pdf_bytes' in st.session_state and st.session_state.pdf_bytes:
227
+ st.success("Seu relatório está pronto para download!")
228
+ st.download_button(
229
+ label="Baixar PDF",
230
+ data=st.session_state.pdf_bytes,
231
+ file_name=st.session_state.file_name,
232
+ mime="application/pdf"
233
+ )