412 lines
11 KiB
TypeScript
412 lines
11 KiB
TypeScript
import { Router } from 'express';
|
|
import { prisma } from '../prismaClient';
|
|
import { authMiddleware } from '../../middleware/auth';
|
|
import { TipoDocumento } from '@prisma/client';
|
|
import { PdfService } from '../services/PdfService';
|
|
import multer from 'multer';
|
|
import path from 'path';
|
|
import fs from 'fs';
|
|
|
|
const router = Router();
|
|
|
|
router.use(authMiddleware);
|
|
|
|
// Listar documentos
|
|
router.get('/', async (req, res) => {
|
|
try {
|
|
const { processoId, atendimentoId, tipo } = req.query;
|
|
|
|
const where: any = {};
|
|
if (processoId) where.processoId = processoId;
|
|
if (atendimentoId) where.atendimentoId = atendimentoId;
|
|
if (tipo) where.tipo = tipo as TipoDocumento;
|
|
|
|
const documentos = await prisma.documento.findMany({
|
|
where,
|
|
include: {
|
|
criadoPor: {
|
|
select: {
|
|
id: true,
|
|
nome: true
|
|
}
|
|
}
|
|
},
|
|
orderBy: {
|
|
criadoEm: 'desc'
|
|
}
|
|
});
|
|
|
|
res.json(documentos);
|
|
} catch (error) {
|
|
console.error('Erro ao listar documentos:', error);
|
|
res.status(500).json({ error: 'Erro ao listar documentos' });
|
|
}
|
|
});
|
|
|
|
// Criar documento
|
|
router.post('/', async (req, res) => {
|
|
try {
|
|
const { nome, tipo, conteudo, processoId, atendimentoId } = req.body;
|
|
|
|
if (!req.user?.id) {
|
|
return res.status(401).json({ error: 'Usuário não autenticado' });
|
|
}
|
|
|
|
const documento = await prisma.documento.create({
|
|
data: {
|
|
nome,
|
|
tipo,
|
|
conteudo,
|
|
processoId,
|
|
atendimentoId,
|
|
criadoPorId: req.user.id
|
|
}
|
|
});
|
|
|
|
res.status(201).json(documento);
|
|
} catch (error) {
|
|
console.error('Erro ao criar documento:', error);
|
|
res.status(500).json({ error: 'Erro ao criar documento' });
|
|
}
|
|
});
|
|
|
|
// Criar documento a partir de modelo
|
|
router.post('/from-modelo/:modeloId', async (req, res) => {
|
|
try {
|
|
const { modeloId } = req.params;
|
|
const { processoId, atendimentoId, variaveis } = req.body;
|
|
|
|
if (!req.user?.id) {
|
|
return res.status(401).json({ error: 'Usuário não autenticado' });
|
|
}
|
|
|
|
// Buscar modelo
|
|
const modelo = await prisma.documentoModelo.findUnique({
|
|
where: { id: modeloId }
|
|
});
|
|
|
|
if (!modelo) {
|
|
return res.status(404).json({ error: 'Modelo não encontrado' });
|
|
}
|
|
|
|
// Buscar dados adicionais se necessário
|
|
let clienteData;
|
|
if (variaveis?.cliente?.id) {
|
|
const cliente = await prisma.cliente.findUnique({
|
|
where: { id: variaveis.cliente.id }
|
|
});
|
|
if (cliente) {
|
|
clienteData = cliente;
|
|
}
|
|
}
|
|
|
|
// Substituir variáveis no conteúdo
|
|
let conteudo = modelo.conteudo;
|
|
if (clienteData) {
|
|
const substituicoes = {
|
|
'cliente.nome': clienteData.nome,
|
|
'cliente.cpf': clienteData.cpfCnpj,
|
|
'cliente.rg': clienteData.rg,
|
|
'cliente.estadoCivil': clienteData.estadoCivil,
|
|
'cliente.profissao': clienteData.profissao,
|
|
'cliente.enderecoCompleto': clienteData.enderecoCompleto,
|
|
'data.atualExtenso': new Date().toLocaleDateString('pt-BR', {
|
|
day: 'numeric',
|
|
month: 'long',
|
|
year: 'numeric'
|
|
})
|
|
};
|
|
|
|
Object.entries(substituicoes).forEach(([key, value]) => {
|
|
const regex = new RegExp(`{{${key}}}`, 'g');
|
|
conteudo = conteudo.replace(regex, value || '');
|
|
});
|
|
}
|
|
|
|
// Criar o documento
|
|
const documento = await prisma.documento.create({
|
|
data: {
|
|
nome: modelo.nome, // Usando o nome do modelo
|
|
tipo: modelo.tipo,
|
|
conteudo,
|
|
processoId,
|
|
atendimentoId,
|
|
criadoPorId: req.user.id,
|
|
modeloId: modelo.id
|
|
}
|
|
});
|
|
|
|
res.status(201).json({
|
|
...documento,
|
|
clienteId: variaveis?.cliente?.id
|
|
});
|
|
} catch (error) {
|
|
console.error('Erro ao criar documento:', error);
|
|
res.status(500).json({ error: 'Erro ao criar documento' });
|
|
}
|
|
});
|
|
|
|
// Atualizar a rota de configurações
|
|
router.post('/configuracoes', async (req, res) => {
|
|
try {
|
|
const escritorioId = req.user.escritorioId; // Assumindo que você tem o ID do escritório no token
|
|
|
|
// Usar upsert para criar ou atualizar
|
|
const config = await prisma.configuracaoDocumento.upsert({
|
|
where: {
|
|
escritorioId
|
|
},
|
|
update: {
|
|
...req.body,
|
|
margensTemplate: req.body.margensTemplate || {
|
|
top: 35,
|
|
bottom: 29,
|
|
left: 25,
|
|
right: 25
|
|
}
|
|
},
|
|
create: {
|
|
escritorioId,
|
|
...req.body,
|
|
margensTemplate: req.body.margensTemplate || {
|
|
top: 35,
|
|
bottom: 29,
|
|
left: 25,
|
|
right: 25
|
|
}
|
|
}
|
|
});
|
|
|
|
res.json(config);
|
|
} catch (error) {
|
|
console.error('Erro ao salvar configuração:', error);
|
|
res.status(500).json({ error: 'Erro ao salvar configuração' });
|
|
}
|
|
});
|
|
|
|
// Rota para buscar última configuração
|
|
router.get('/configuracoes', async (req, res) => {
|
|
try {
|
|
console.log('Buscando configurações de documento');
|
|
|
|
const config = await prisma.configuracaoDocumento.findFirst({
|
|
orderBy: {
|
|
criadoEm: 'desc'
|
|
}
|
|
});
|
|
|
|
if (!config) {
|
|
// Criar configuração padrão se não existir
|
|
const defaultConfig = await prisma.configuracaoDocumento.create({
|
|
data: {
|
|
timbradoMarginTop: 100,
|
|
timbradoMarginBottom: 50,
|
|
timbradoMarginLeft: 50,
|
|
timbradoMarginRight: 50,
|
|
margensTemplate: {
|
|
top: 113,
|
|
bottom: 90,
|
|
left: 35,
|
|
right: 35
|
|
}
|
|
}
|
|
});
|
|
return res.json(defaultConfig);
|
|
}
|
|
|
|
res.json(config);
|
|
} catch (error) {
|
|
console.error('Erro ao buscar configurações:', error);
|
|
res.status(500).json({ error: 'Erro ao buscar configurações' });
|
|
}
|
|
});
|
|
|
|
// Atualizar configuração do documento
|
|
router.post('/configuracao', authMiddleware, async (req, res) => {
|
|
try {
|
|
// Primeiro, tente encontrar uma configuração existente
|
|
const configExistente = await prisma.configuracaoDocumento.findFirst({
|
|
where: {
|
|
escritorioId: req.user.escritorioId
|
|
}
|
|
});
|
|
|
|
let config;
|
|
|
|
if (configExistente) {
|
|
// Se existir, atualiza
|
|
config = await prisma.configuracaoDocumento.update({
|
|
where: {
|
|
id: configExistente.id
|
|
},
|
|
data: {
|
|
timbradoUrl: req.body.timbradoUrl,
|
|
timbradoMarginTop: req.body.timbradoMarginTop,
|
|
timbradoMarginBottom: req.body.timbradoMarginBottom,
|
|
timbradoMarginLeft: req.body.timbradoMarginLeft,
|
|
timbradoMarginRight: req.body.timbradoMarginRight,
|
|
templatePadrao: req.body.templatePadrao || "",
|
|
margensTemplate: req.body.margensTemplate
|
|
}
|
|
});
|
|
} else {
|
|
// Se não existir, cria
|
|
config = await prisma.configuracaoDocumento.create({
|
|
data: {
|
|
escritorioId: req.user.escritorioId,
|
|
timbradoUrl: req.body.timbradoUrl,
|
|
timbradoMarginTop: req.body.timbradoMarginTop,
|
|
timbradoMarginBottom: req.body.timbradoMarginBottom,
|
|
timbradoMarginLeft: req.body.timbradoMarginLeft,
|
|
timbradoMarginRight: req.body.timbradoMarginRight,
|
|
templatePadrao: req.body.templatePadrao || "",
|
|
margensTemplate: req.body.margensTemplate
|
|
}
|
|
});
|
|
}
|
|
|
|
res.json(config);
|
|
} catch (error) {
|
|
console.error('Erro ao salvar configuração:', error);
|
|
res.status(500).json({ error: 'Falha ao salvar configuração do documento' });
|
|
}
|
|
});
|
|
|
|
// Atualizar documento com manipulação de erro aprimorada
|
|
router.put('/:id', async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
const { nome, tipo, conteudo } = req.body;
|
|
|
|
// Verificar se o documento existe
|
|
const documentoExistente = await prisma.documento.findUnique({
|
|
where: { id },
|
|
select: { id: true, criadoPorId: true }
|
|
});
|
|
|
|
if (!documentoExistente) {
|
|
return res.status(404).json({ error: 'Documento não encontrado' });
|
|
}
|
|
|
|
// Verificar permissão (apenas quem criou ou é admin pode editar)
|
|
if (documentoExistente.criadoPorId !== req.user.id && req.user.perfil !== 'ADVOGADO_ADMIN') {
|
|
return res.status(403).json({ error: 'Sem permissão para editar este documento' });
|
|
}
|
|
|
|
// Validar dados
|
|
if (!nome || !tipo || !conteudo) {
|
|
return res.status(400).json({ error: 'Dados incompletos para atualização do documento' });
|
|
}
|
|
|
|
// Atualizar o documento
|
|
const documento = await prisma.documento.update({
|
|
where: { id },
|
|
data: {
|
|
nome,
|
|
tipo: tipo as TipoDocumento,
|
|
conteudo,
|
|
atualizadoEm: new Date()
|
|
}
|
|
});
|
|
|
|
// Registrar evento de atualização (opcional)
|
|
// await prisma.auditoria.create({
|
|
// data: {
|
|
// entidade: 'DOCUMENTO',
|
|
// entidadeId: id,
|
|
// acao: 'ATUALIZAÇÃO',
|
|
// usuarioId: req.user.id
|
|
// }
|
|
// });
|
|
|
|
res.json(documento);
|
|
} catch (error) {
|
|
console.error('Erro ao atualizar documento:', error);
|
|
res.status(500).json({ error: 'Erro ao atualizar documento' });
|
|
}
|
|
});
|
|
|
|
// Excluir documento
|
|
router.delete('/:id', async (req, res) => {
|
|
try {
|
|
await prisma.documento.delete({
|
|
where: { id: req.params.id }
|
|
});
|
|
res.status(204).send();
|
|
} catch (error) {
|
|
console.error('Erro ao excluir documento:', error);
|
|
res.status(500).json({ error: 'Erro ao excluir documento' });
|
|
}
|
|
});
|
|
|
|
// Adicionar nova rota para exportar PDF
|
|
router.post('/exportar-pdf', async (req, res) => {
|
|
try {
|
|
const { conteudo, escritorio } = req.body;
|
|
|
|
const pdfService = new PdfService();
|
|
const pdfBuffer = await pdfService.gerarPDF(conteudo, escritorio);
|
|
|
|
res.setHeader('Content-Type', 'application/pdf');
|
|
res.setHeader('Content-Disposition', 'attachment; filename=documento.pdf');
|
|
res.send(pdfBuffer);
|
|
|
|
} catch (error) {
|
|
console.error('Erro ao gerar PDF:', error);
|
|
res.status(500).json({ error: 'Erro ao gerar PDF' });
|
|
}
|
|
});
|
|
|
|
// Configuração do multer para upload de arquivos
|
|
const storage = multer.diskStorage({
|
|
destination: (req, file, cb) => {
|
|
const uploadDir = path.join(process.cwd(), 'public', 'uploads');
|
|
if (!fs.existsSync(uploadDir)) {
|
|
fs.mkdirSync(uploadDir, { recursive: true });
|
|
}
|
|
cb(null, uploadDir);
|
|
},
|
|
filename: (req, file, cb) => {
|
|
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
|
|
cb(null, `timbrado-${uniqueSuffix}-${file.originalname}`);
|
|
}
|
|
});
|
|
|
|
const fileFilter = (req: any, file: any, cb: any) => {
|
|
// Atualizar para aceitar PDF
|
|
const allowedTypes = ['image/png', 'image/svg+xml', 'application/pdf'];
|
|
|
|
if (allowedTypes.includes(file.mimetype)) {
|
|
cb(null, true);
|
|
} else {
|
|
cb(new Error('Formato de arquivo não suportado. Use PNG, SVG ou PDF.'));
|
|
}
|
|
};
|
|
|
|
const upload = multer({
|
|
storage,
|
|
fileFilter,
|
|
limits: {
|
|
fileSize: 5 * 1024 * 1024 // Aumentar para 5MB
|
|
}
|
|
});
|
|
|
|
// Rota de upload do timbrado
|
|
router.post('/upload-timbrado', upload.single('timbrado'), async (req, res) => {
|
|
try {
|
|
if (!req.file) {
|
|
throw new Error('Nenhum arquivo enviado');
|
|
}
|
|
|
|
// Criar URL relativa para o arquivo
|
|
const fileUrl = `/uploads/${req.file.filename}`;
|
|
|
|
res.json({ url: fileUrl });
|
|
} catch (error: any) {
|
|
console.error('Erro no upload do timbrado:', error);
|
|
res.status(400).json({ error: error.message });
|
|
}
|
|
});
|
|
|
|
export default router;
|