Spaces:
Sleeping
Sleeping
Update src/app.py
Browse files- src/app.py +129 -34
src/app.py
CHANGED
|
@@ -167,47 +167,142 @@ def create_pdf_report(user_data):
|
|
| 167 |
def create_docx_report(user_data):
|
| 168 |
doc = Document()
|
| 169 |
|
| 170 |
-
#
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
| 187 |
-
|
| 188 |
-
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
|
| 194 |
-
|
| 195 |
-
doc.add_paragraph(
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
doc.add_paragraph(
|
| 199 |
-
|
| 200 |
-
|
| 201 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 202 |
|
| 203 |
# Data final
|
| 204 |
today = date.today()
|
| 205 |
meses = ("janeiro", "fevereiro", "março", "abril", "maio", "junho",
|
| 206 |
"julho", "agosto", "setembro", "outubro", "novembro", "dezembro")
|
| 207 |
data_formatada = f"Porto Alegre, {today.day} de {meses[today.month - 1]} de {today.year}."
|
| 208 |
-
doc.add_paragraph(
|
|
|
|
|
|
|
| 209 |
|
| 210 |
-
# Salvar
|
| 211 |
doc_io = BytesIO()
|
| 212 |
doc.save(doc_io)
|
| 213 |
doc_io.seek(0)
|
|
|
|
| 167 |
def create_docx_report(user_data):
|
| 168 |
doc = Document()
|
| 169 |
|
| 170 |
+
# --- Inserir Logos no topo, lado a lado se existirem ---
|
| 171 |
+
# Cria uma tabela com 1 linha, 2 colunas para os logos, para alinhá-los
|
| 172 |
+
table = doc.add_table(rows=1, cols=2)
|
| 173 |
+
table.autofit = False
|
| 174 |
+
widths = [Inches(2), Inches(2)] # ajuste largura das colunas
|
| 175 |
+
|
| 176 |
+
for i, width in enumerate(widths):
|
| 177 |
+
table.columns[i].width = width
|
| 178 |
+
|
| 179 |
+
# Logo 1: 'src/logo_pref.png'
|
| 180 |
+
if os.path.exists('src/logo_pref.png'):
|
| 181 |
+
cell_logo_pref = table.cell(0,0)
|
| 182 |
+
paragraph = cell_logo_pref.paragraphs[0]
|
| 183 |
+
run = paragraph.add_run()
|
| 184 |
+
run.add_picture('src/logo_pref.png', width=Inches(2))
|
| 185 |
+
paragraph.alignment = WD_ALIGN_PARAGRAPH.LEFT
|
| 186 |
+
|
| 187 |
+
# Logo 2: 'src/logo_receita.png'
|
| 188 |
+
if os.path.exists('src/logo_receita.png'):
|
| 189 |
+
cell_logo_receita = table.cell(0,1)
|
| 190 |
+
paragraph = cell_logo_receita.paragraphs[0]
|
| 191 |
+
run = paragraph.add_run()
|
| 192 |
+
run.add_picture('src/logo_receita.png', width=Inches(1.75))
|
| 193 |
+
paragraph.alignment = WD_ALIGN_PARAGRAPH.RIGHT
|
| 194 |
+
|
| 195 |
+
doc.add_paragraph() # espaço depois dos logos
|
| 196 |
+
|
| 197 |
+
# --- Cabeçalho texto à direita (igual PDF) ---
|
| 198 |
+
p = doc.add_paragraph()
|
| 199 |
+
p.alignment = WD_ALIGN_PARAGRAPH.RIGHT
|
| 200 |
+
run = p.add_run("DAI-ESJL\nDivisão de Avaliação de Imóveis\nEquipe de Suporte, Judiciais e Locações")
|
| 201 |
+
font = run.font
|
| 202 |
+
font.size = Pt(8)
|
| 203 |
+
font.bold = True
|
| 204 |
+
|
| 205 |
+
# Número do processo (abaixo do cabeçalho)
|
| 206 |
+
p_proc = doc.add_paragraph(f"PROCESSO {user_data.get('processo_numero','')}")
|
| 207 |
+
p_proc.alignment = WD_ALIGN_PARAGRAPH.RIGHT
|
| 208 |
+
run_proc = p_proc.runs[0]
|
| 209 |
+
run_proc.font.size = Pt(10)
|
| 210 |
+
run_proc.font.bold = True
|
| 211 |
+
|
| 212 |
+
doc.add_paragraph() # espaço
|
| 213 |
+
|
| 214 |
+
# --- Função auxiliar para criar tabelas simples ---
|
| 215 |
+
def add_table_from_data(data, col_widths_cm=[4.5, 10]):
|
| 216 |
+
table = doc.add_table(rows=0, cols=2)
|
| 217 |
+
table.style = 'Table Grid'
|
| 218 |
+
# Ajustar larguras das colunas
|
| 219 |
+
for idx, width in enumerate(col_widths_cm):
|
| 220 |
+
for cell in table.columns[idx].cells:
|
| 221 |
+
cell.width = Cm(width)
|
| 222 |
+
|
| 223 |
+
for label, content in data:
|
| 224 |
+
row_cells = table.add_row().cells
|
| 225 |
+
# Primeira coluna - bold
|
| 226 |
+
p_label = row_cells[0].paragraphs[0]
|
| 227 |
+
run_label = p_label.add_run(label)
|
| 228 |
+
run_label.bold = True
|
| 229 |
+
p_label.alignment = WD_ALIGN_PARAGRAPH.LEFT
|
| 230 |
+
|
| 231 |
+
# Segunda coluna - normal
|
| 232 |
+
p_content = row_cells[1].paragraphs[0]
|
| 233 |
+
p_content.add_run(str(content))
|
| 234 |
+
p_content.alignment = WD_ALIGN_PARAGRAPH.LEFT
|
| 235 |
+
|
| 236 |
+
doc.add_paragraph() # espaço depois da tabela
|
| 237 |
+
return table
|
| 238 |
+
|
| 239 |
+
from docx.shared import Cm # para centímetros
|
| 240 |
+
|
| 241 |
+
# --- Conteúdo do relatório ---
|
| 242 |
+
|
| 243 |
+
# Título principal centralizado
|
| 244 |
+
title = doc.add_paragraph(f"INFORMAÇÃO TÉCNICA\nIT_{user_data.get('it_numero','')}")
|
| 245 |
+
title.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
| 246 |
+
title.runs[0].font.size = Pt(14)
|
| 247 |
+
title.runs[0].font.bold = True
|
| 248 |
+
|
| 249 |
+
# Página 1 - Solicitação
|
| 250 |
+
doc.add_heading("• SOLICITAÇÃO", level=2)
|
| 251 |
+
solicitacao_data = [
|
| 252 |
+
('Unidade demandante:', user_data.get('unidade_demandante','')),
|
| 253 |
+
('Finalidade da Avaliação:', user_data.get('finalidade_avaliacao',''))
|
| 254 |
+
]
|
| 255 |
+
add_table_from_data(solicitacao_data)
|
| 256 |
+
|
| 257 |
+
# Imóvel objeto
|
| 258 |
+
doc.add_heading("• IMÓVEL OBJETO", level=2)
|
| 259 |
+
imovel_data = [
|
| 260 |
+
('Endereço - SMF:', user_data.get('endereco_smf','')),
|
| 261 |
+
('Bairro (Setor/Quarteirão) - SMF:', user_data.get('bairro_smf','')),
|
| 262 |
+
('Lote Fiscal / Inscrição - SMF:', user_data.get('lote_fiscal','')),
|
| 263 |
+
('Registro imóvel nº - SMF:', user_data.get('registro_imovel','')),
|
| 264 |
+
('Finalidade Imóvel - SMF:', user_data.get('finalidade_imovel','')),
|
| 265 |
+
('Área Territorial - SMF:', user_data.get('area_territorial','')),
|
| 266 |
+
('Área construída – SMF:', user_data.get('area_construida','')),
|
| 267 |
+
('Exercícios em análise:', user_data.get('exercicios_analise','')),
|
| 268 |
+
('Valores Venais Guias IPTU (Exercícios):', user_data.get('valores_venais',''))
|
| 269 |
+
]
|
| 270 |
+
add_table_from_data(imovel_data)
|
| 271 |
+
|
| 272 |
+
# Página 2 - Análise técnica preliminar
|
| 273 |
+
doc.add_heading("• ANÁLISE TÉCNICA PRELIMINAR", level=2)
|
| 274 |
+
analise_data = [
|
| 275 |
+
('Unidade responsável:', user_data.get('unidade_responsavel','')),
|
| 276 |
+
('Técnico responsável:', user_data.get('tecnico_responsavel','')),
|
| 277 |
+
('Método de Avaliação (ABNT NBR 14.653-2):', user_data.get('metodo_avaliacao',''))
|
| 278 |
+
]
|
| 279 |
+
add_table_from_data(analise_data)
|
| 280 |
+
|
| 281 |
+
# Conclusão técnica
|
| 282 |
+
doc.add_heading("• CONCLUSÃO TÉCNICA", level=2)
|
| 283 |
+
conclusao_data = [
|
| 284 |
+
('Características particularmente\ndesvalorizantes:', user_data.get('caracteristicas_desvalorizantes','')),
|
| 285 |
+
('Conclusão:', user_data.get('conclusao_preliminar',''))
|
| 286 |
+
]
|
| 287 |
+
add_table_from_data(conclusao_data)
|
| 288 |
+
|
| 289 |
+
# Textos longos
|
| 290 |
+
doc.add_heading("1. CONSIDERAÇÕES INICIAIS", level=2)
|
| 291 |
+
doc.add_paragraph(user_data.get('texto_consideracoes',''))
|
| 292 |
+
|
| 293 |
+
doc.add_heading("2. ANÁLISE TÉCNICA PRELIMINAR", level=2)
|
| 294 |
+
doc.add_paragraph(user_data.get('texto_analise',''))
|
| 295 |
|
| 296 |
# Data final
|
| 297 |
today = date.today()
|
| 298 |
meses = ("janeiro", "fevereiro", "março", "abril", "maio", "junho",
|
| 299 |
"julho", "agosto", "setembro", "outubro", "novembro", "dezembro")
|
| 300 |
data_formatada = f"Porto Alegre, {today.day} de {meses[today.month - 1]} de {today.year}."
|
| 301 |
+
p_date = doc.add_paragraph()
|
| 302 |
+
p_date.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
| 303 |
+
p_date.add_run(data_formatada)
|
| 304 |
|
| 305 |
+
# Salvar em memória
|
| 306 |
doc_io = BytesIO()
|
| 307 |
doc.save(doc_io)
|
| 308 |
doc_io.seek(0)
|