1505 lines
41 KiB
TypeScript
1505 lines
41 KiB
TypeScript
import express from "express";
|
|
import cors from "cors";
|
|
import axios from "axios";
|
|
import "dotenv/config";
|
|
import { prisma } from './prismaClient'; // Corrigir o import do prisma
|
|
import { AuthService } from "../services/AuthService";
|
|
import { UsuarioRepository } from "../repositories/UsuarioRepository";
|
|
import { ClienteRepository } from "../repositories/ClienteRepository";
|
|
import { ProcessoRepository } from "../repositories/ProcessoRepository";
|
|
import { OrgaoJulgadorRepository } from "../repositories/OrgaoJulgadorRepository";
|
|
import { CustaProcessualRepository } from "../repositories/CustaProcessualRepository";
|
|
import { HonorarioRepository } from "../repositories/HonorarioRepository";
|
|
import jwt from "jsonwebtoken";
|
|
import { authMiddleware } from '../middleware/auth';
|
|
import bcrypt from "bcryptjs";
|
|
import { TipoAtendimento } from "@prisma/client"; // Adicionar esta importação
|
|
import tarefasRoutes from './routes/tarefas';
|
|
import dashboardRoutes from './routes/dashboard';
|
|
import atendimentosRoutes from './routes/atendimentos';
|
|
import anexosRoutes from './routes/anexos';
|
|
import documentosRouter from './routes/documentos';
|
|
import documentosModelosRouter from './routes/documentos-modelos';
|
|
import processosAdministrativosRoutes from './routes/processosAdministrativos';
|
|
import provasRouter from './routes/provas';
|
|
import calculosJudiciaisRoutes from './routes/calculosJudiciais';
|
|
import indicesMonetariosRoutes from './routes/indicesMonetarios';
|
|
import pensaoAlimenticiaRouter from './routes/pensaoAlimenticia'; // Importar router de pensão alimentícia
|
|
import financeiroPainelRoutes from './routes/financeiroPainel'; // Importar rotas do financeiro painel
|
|
import audienciasRoutes from './routes/audiencias'; // Importar rotas de audiências
|
|
import pdfRoutes from './routes/pdf'; // Importar rotas de PDF
|
|
import { PDFService } from '../services/pdfService'; // Importar serviço de PDF para warmup OCR
|
|
|
|
|
|
const app = express();
|
|
const port = process.env.PORT || 5000;
|
|
const corsOrigin = process.env.CORS_ORIGIN || "http://localhost:3000";
|
|
|
|
app.use(
|
|
cors({
|
|
origin: corsOrigin,
|
|
methods: ["GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"],
|
|
allowedHeaders: ["Content-Type", "Authorization", "X-Requested-With"],
|
|
exposedHeaders: ["Content-Range", "X-Content-Range"],
|
|
credentials: true,
|
|
}),
|
|
);
|
|
|
|
// Adicionar headers específicos para CORS
|
|
app.use((req, res, next) => {
|
|
res.header("Access-Control-Allow-Origin", corsOrigin);
|
|
res.header("Access-Control-Allow-Credentials", "true");
|
|
next();
|
|
});
|
|
|
|
app.use(express.json({ limit: '20mb' }));
|
|
app.use(express.urlencoded({ extended: true, limit: '20mb' }));
|
|
|
|
const clienteRepository = new ClienteRepository();
|
|
const processoRepository = new ProcessoRepository();
|
|
const orgaoJulgadorRepository = new OrgaoJulgadorRepository();
|
|
const custaProcessualRepository = new CustaProcessualRepository();
|
|
const honorarioRepository = new HonorarioRepository();
|
|
|
|
// Atualizar a função isValidUUID para ser mais robusta
|
|
const isValidUUID = (uuid: string | null | undefined): boolean => {
|
|
if (!uuid) return false;
|
|
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
return uuidRegex.test(uuid);
|
|
};
|
|
|
|
// Middleware para extrair usuário do token
|
|
// Remover este middleware pois já temos o auth.ts
|
|
// const extractUser = (req: any, res: any, next: any) => { ... }
|
|
// app.use(extractUser);
|
|
|
|
// Rota de teste
|
|
app.get("/api/health", (req, res) => {
|
|
res.json({ status: "ok", timestamp: new Date() });
|
|
});
|
|
|
|
app.post("/api/auth/login", async (req, res) => {
|
|
try {
|
|
console.log("Server - Request de login:", req.body); // Debug
|
|
|
|
const { email, senha } = req.body;
|
|
const authService = new AuthService(new UsuarioRepository());
|
|
const result = await authService.login(email, senha);
|
|
console.log("Server - Login bem-sucedido:", { userId: result.user.id }); // Debug
|
|
|
|
res.json(result);
|
|
} catch (error) {
|
|
console.error("Server - Erro no login:", error); // Debug
|
|
|
|
const message =
|
|
error instanceof Error ? error.message : "Erro ao fazer login";
|
|
res.status(401).json({ error: message });
|
|
}
|
|
});
|
|
|
|
app.get("/auth/verify", async (req, res) => {
|
|
try {
|
|
const token = req.headers.authorization?.replace("Bearer ", "");
|
|
if (!token) {
|
|
return res.status(401).json({ error: "Token não fornecido" });
|
|
}
|
|
|
|
const decoded = jwt.verify(
|
|
token,
|
|
process.env.JWT_SECRET || "default-secret",
|
|
);
|
|
if (!decoded) {
|
|
return res.status(401).json({ error: "Token inválido" });
|
|
}
|
|
|
|
res.json({ valid: true });
|
|
} catch (error) {
|
|
res.status(401).json({ error: "Token inválido" });
|
|
}
|
|
});
|
|
|
|
// Redirecionar para página pública de verificação (atualizar esta rota)
|
|
app.get('/verificar/:hash', (req, res) => {
|
|
// Redirecionar para a verificação pública (sem login)
|
|
res.redirect(`${process.env.FRONTEND_URL || 'http://localhost:3000'}/public/verificar/${req.params.hash}`);
|
|
});
|
|
|
|
// Rota para buscar perfil do usuário logado (ajuste do caminho)
|
|
app.get("/api/auth/me", async (req, res) => {
|
|
// Adicionado prefixo /api
|
|
try {
|
|
const token = req.headers.authorization?.replace("Bearer ", "");
|
|
if (!token) {
|
|
console.log("Token não fornecido");
|
|
return res.status(401).json({ error: "Token não fornecido" });
|
|
}
|
|
|
|
const decoded = jwt.verify(
|
|
token,
|
|
process.env.JWT_SECRET || "default-secret",
|
|
) as any;
|
|
console.log("Token decodificado:", decoded);
|
|
|
|
const user = await prisma.usuario.findUnique({ // usar o prisma importado
|
|
where: { id: decoded.id },
|
|
select: {
|
|
id: true,
|
|
nome: true,
|
|
email: true,
|
|
perfil: true,
|
|
ativo: true,
|
|
},
|
|
});
|
|
|
|
if (!user) {
|
|
console.log("Usuário não encontrado:", decoded.id);
|
|
return res.status(404).json({ error: "Usuário não encontrado" });
|
|
}
|
|
|
|
if (!user.ativo) {
|
|
console.log("Usuário inativo:", decoded.id);
|
|
return res.status(401).json({ error: "Usuário inativo" });
|
|
}
|
|
|
|
console.log("Usuário autenticado:", user);
|
|
res.json(user);
|
|
} catch (error) {
|
|
console.error("Erro na autenticação:", error);
|
|
res.status(401).json({ error: "Token inválido" });
|
|
}
|
|
});
|
|
|
|
// Rotas de Clientes
|
|
app.get("/api/clientes", async (req, res) => {
|
|
try {
|
|
const clientes = await clienteRepository.findAll();
|
|
console.log("Clientes encontrados:", clientes.length);
|
|
res.json(clientes);
|
|
} catch (error) {
|
|
console.error("Erro ao buscar clientes:", error);
|
|
res.status(500).json({
|
|
error: "Erro ao buscar clientes",
|
|
details: error instanceof Error ? error.message : "Erro desconhecido",
|
|
});
|
|
}
|
|
});
|
|
|
|
app.post("/api/clientes", async (req, res) => {
|
|
try {
|
|
const requiredFields = [
|
|
"nome",
|
|
"email",
|
|
"telefone",
|
|
"cpfCnpj",
|
|
"endereco",
|
|
"cep",
|
|
"numero",
|
|
"bairro",
|
|
"cidade",
|
|
"estado",
|
|
];
|
|
const missingFields = requiredFields.filter((field) => !req.body[field]);
|
|
|
|
if (missingFields.length > 0) {
|
|
return res.status(400).json({
|
|
error: `Campos obrigatórios faltando: ${missingFields.join(", ")}`,
|
|
missingFields,
|
|
});
|
|
}
|
|
|
|
const cleanData = {
|
|
...req.body,
|
|
renda: req.body.renda ? Number(req.body.renda) : null,
|
|
declaraIR: Boolean(req.body.declaraIR),
|
|
contribuiPrevidencia: Boolean(req.body.contribuiPrevidencia),
|
|
};
|
|
|
|
console.log("Dados recebidos:", cleanData);
|
|
|
|
const cliente = await clienteRepository.create(cleanData);
|
|
res.status(201).json(cliente);
|
|
} catch (error) {
|
|
console.error("Erro ao criar cliente:", error);
|
|
res.status(400).json({
|
|
error: error instanceof Error ? error.message : "Erro ao criar cliente",
|
|
details: error,
|
|
});
|
|
}
|
|
});
|
|
|
|
app.put("/api/clientes/:id", async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
console.log("Atualizando cliente:", id, req.body);
|
|
|
|
const cleanData = {
|
|
...req.body,
|
|
renda: req.body.renda ? Number(req.body.renda) : undefined,
|
|
declaraIR:
|
|
req.body.declaraIR === undefined
|
|
? undefined
|
|
: Boolean(req.body.declaraIR),
|
|
contribuiPrevidencia:
|
|
req.body.contribuiPrevidencia === undefined
|
|
? undefined
|
|
: Boolean(req.body.contribuiPrevidencia),
|
|
};
|
|
|
|
const cliente = await clienteRepository.update(id, cleanData);
|
|
res.json(cliente);
|
|
} catch (error) {
|
|
console.error("Erro ao atualizar cliente:", error);
|
|
res.status(400).json({
|
|
error:
|
|
error instanceof Error ? error.message : "Erro ao atualizar cliente",
|
|
details: error,
|
|
});
|
|
}
|
|
});
|
|
|
|
app.delete("/api/clientes/:id", async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
await clienteRepository.delete(id);
|
|
res.status(204).send();
|
|
} catch (error) {
|
|
console.error("Erro ao deletar cliente:", error);
|
|
res.status(400).json({ error: "Erro ao deletar cliente" });
|
|
}
|
|
});
|
|
|
|
// IMPORTANTE: Mover esta rota ANTES das rotas com parâmetros
|
|
app.get("/api/processos/orgaos", async (req, res) => {
|
|
try {
|
|
const orgaos = await prisma.processo.findMany({
|
|
select: {
|
|
orgaoJulgador: true,
|
|
},
|
|
where: {
|
|
orgaoJulgador: {
|
|
not: null,
|
|
not: "", // Garante que não está vazio também
|
|
},
|
|
},
|
|
distinct: ["orgaoJulgador"],
|
|
});
|
|
|
|
const orgaosUnicos = orgaos
|
|
.map((o) => o.orgaoJulgador)
|
|
.filter(Boolean) // Remove valores null/undefined
|
|
.filter((org): org is string => org !== "") // Remove strings vazias e satisfaz o TypeScript
|
|
.sort();
|
|
|
|
res.json(orgaosUnicos);
|
|
} catch (error) {
|
|
console.error("Erro ao buscar órgãos:", error);
|
|
res.status(500).json({ error: "Erro ao buscar órgãos" });
|
|
}
|
|
});
|
|
|
|
// Adicionar este endpoint antes das outras rotas de processos
|
|
app.patch('/api/processos/:id/resultado', async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
const { resultado } = req.body;
|
|
|
|
const processo = await prisma.processo.update({
|
|
where: { id },
|
|
data: {
|
|
resultado,
|
|
dataAtualizacao: new Date()
|
|
}
|
|
});
|
|
|
|
res.json(processo);
|
|
} catch (error) {
|
|
console.error('Erro ao atualizar resultado:', error);
|
|
res.status(500).json({ error: 'Erro ao atualizar resultado do processo' });
|
|
}
|
|
});
|
|
|
|
// Rotas de Processos
|
|
app.get("/api/processos", async (req, res) => {
|
|
try {
|
|
const processos = await processoRepository.findAll();
|
|
res.json(processos);
|
|
} catch (error) {
|
|
console.error("Erro ao buscar processos:", error);
|
|
res.status(500).json({ error: "Erro ao buscar processos" });
|
|
}
|
|
});
|
|
|
|
app.post("/api/processos", async (req, res) => {
|
|
try {
|
|
const processo = await processoRepository.create(req.body);
|
|
res.status(201).json(processo);
|
|
} catch (error) {
|
|
console.error("Erro ao criar processo:", error);
|
|
res.status(400).json({ error: "Erro ao criar processo" });
|
|
}
|
|
});
|
|
|
|
app.get("/api/processos/:id", async (req, res) => {
|
|
try {
|
|
const processo = await prisma.processo.findUnique({
|
|
where: { id: req.params.id },
|
|
include: {
|
|
partes: true,
|
|
diligencias: true,
|
|
audiencias: true,
|
|
documentos: true,
|
|
movimentacoes: true,
|
|
honorarios: {
|
|
include: {
|
|
parcelas: true,
|
|
},
|
|
},
|
|
custas: true,
|
|
},
|
|
});
|
|
|
|
if (!processo) {
|
|
return res.status(404).json({ error: "Processo não encontrado" });
|
|
}
|
|
res.json(processo);
|
|
} catch (error) {
|
|
console.error("Erro ao buscar processo:", error);
|
|
res.status(500).json({ error: "Erro ao buscar processo" });
|
|
}
|
|
});
|
|
|
|
app.put("/api/processos/:id", async (req, res) => {
|
|
try {
|
|
const processo = await processoRepository.update(req.params.id, req.body);
|
|
res.json(processo);
|
|
} catch (error) {
|
|
console.error("Erro ao atualizar processo:", error);
|
|
res.status(400).json({ error: "Erro ao atualizar processo" });
|
|
}
|
|
});
|
|
|
|
app.delete("/api/processos/:id", async (req, res) => {
|
|
try {
|
|
await processoRepository.delete(req.params.id);
|
|
res.status(204).send();
|
|
} catch (error) {
|
|
console.error("Erro ao deletar processo:", error);
|
|
res.status(400).json({ error: "Erro ao deletar processo" });
|
|
}
|
|
});
|
|
|
|
// Rotas para Partes do Processo
|
|
app.post("/api/processos/:id/partes", async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
const { tipo, nome, cpfCnpj, observacoes, clienteId, principal } = req.body;
|
|
|
|
const parte = await prisma.parteProcesso.create({
|
|
data: {
|
|
tipo,
|
|
nome,
|
|
cpfCnpj,
|
|
observacoes,
|
|
principal: principal || false,
|
|
processo: {
|
|
connect: { id },
|
|
},
|
|
...(clienteId && {
|
|
cliente: {
|
|
connect: { id: clienteId },
|
|
},
|
|
}),
|
|
},
|
|
});
|
|
|
|
res.status(201).json(parte);
|
|
} catch (error) {
|
|
console.error("Erro detalhado ao criar parte:", error);
|
|
res
|
|
.status(400)
|
|
.json({ error: "Erro ao criar parte do processo", details: error });
|
|
}
|
|
});
|
|
|
|
app.put("/api/processos/:processoId/partes/:id", async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
const parte = await prisma.parteProcesso.update({
|
|
where: { id },
|
|
data: req.body,
|
|
});
|
|
res.json(parte);
|
|
} catch (error) {
|
|
console.error("Erro ao atualizar parte:", error);
|
|
res.status(400).json({ error: "Erro ao atualizar parte do processo" });
|
|
}
|
|
});
|
|
|
|
app.delete("/api/processos/:processoId/partes/:id", async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
await prisma.parteProcesso.delete({
|
|
where: { id },
|
|
});
|
|
res.status(204).send();
|
|
} catch (error) {
|
|
console.error("Erro ao deletar parte:", error);
|
|
res.status(400).json({ error: "Erro ao deletar parte do processo" });
|
|
}
|
|
});
|
|
|
|
// Rotas para Audiências do Processo
|
|
app.post("/api/processos/:id/audiencias", async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
const audiencia = await prisma.audiencia.create({
|
|
data: {
|
|
...req.body,
|
|
data: new Date(req.body.data),
|
|
processo: {
|
|
connect: { id },
|
|
},
|
|
},
|
|
});
|
|
res.status(201).json(audiencia);
|
|
} catch (error) {
|
|
console.error("Erro ao criar audiência:", error);
|
|
res.status(400).json({ error: "Erro ao criar audiência" });
|
|
}
|
|
});
|
|
|
|
app.put("/api/processos/:processoId/audiencias/:id", async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
const audiencia = await prisma.audiencia.update({
|
|
where: { id },
|
|
data: {
|
|
...req.body,
|
|
data: new Date(req.body.data),
|
|
},
|
|
});
|
|
res.json(audiencia);
|
|
} catch (error) {
|
|
console.error("Erro ao atualizar audiência:", error);
|
|
res.status(400).json({ error: "Erro ao atualizar audiência" });
|
|
}
|
|
});
|
|
|
|
app.delete("/api/processos/:processoId/audiencias/:id", async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
await prisma.audiencia.delete({
|
|
where: { id },
|
|
});
|
|
res.status(204).send();
|
|
} catch (error) {
|
|
console.error("Erro ao deletar audiência:", error);
|
|
res.status(400).json({ error: "Erro ao deletar audiência" });
|
|
}
|
|
});
|
|
|
|
// Rota para buscar órgãos julgadores
|
|
app.get("/api/orgaos-julgadores", async (req, res) => {
|
|
try {
|
|
const orgaos = await orgaoJulgadorRepository.findAll();
|
|
res.json(orgaos);
|
|
} catch (error) {
|
|
console.error("Erro ao buscar órgãos julgadores:", error);
|
|
res.status(500).json({ error: "Erro ao buscar órgãos julgadores" });
|
|
}
|
|
});
|
|
|
|
// Rota para criar órgão julgador
|
|
app.post("/api/orgaos-julgadores", async (req, res) => {
|
|
try {
|
|
const { nome } = req.body;
|
|
|
|
// Verificar se já existe
|
|
const existente = await prisma.orgaoJulgador.findUnique({
|
|
where: { nome },
|
|
});
|
|
|
|
if (existente) {
|
|
return res.json(existente);
|
|
}
|
|
|
|
// Criar novo
|
|
const orgao = await prisma.orgaoJulgador.create({
|
|
data: { nome },
|
|
});
|
|
|
|
res.status(201).json(orgao);
|
|
} catch (error) {
|
|
console.error("Erro ao criar órgão julgador:", error);
|
|
res.status(400).json({ error: "Erro ao criar órgão julgador" });
|
|
}
|
|
});
|
|
|
|
// Custas Processuais
|
|
app.get("/api/processos/:id/custas", async (req, res) => {
|
|
try {
|
|
const custas = await custaProcessualRepository.findByProcesso(
|
|
req.params.id,
|
|
);
|
|
res.json(custas);
|
|
} catch (error) {
|
|
res.status(500).json({ error: "Erro ao buscar custas processuais" });
|
|
}
|
|
});
|
|
|
|
app.post("/api/processos/:id/custas", async (req, res) => {
|
|
try {
|
|
console.log("Dados recebidos para criar custa:", req.body);
|
|
const custa = await custaProcessualRepository.create({
|
|
...req.body,
|
|
processoId: req.params.id,
|
|
});
|
|
res.json(custa);
|
|
} catch (error) {
|
|
console.error("Erro ao criar custa processual:", error);
|
|
res.status(500).json({
|
|
error: "Erro ao criar custa processual",
|
|
details: error instanceof Error ? error.message : "Erro desconhecido",
|
|
});
|
|
}
|
|
});
|
|
|
|
app.put("/api/custas/:id", async (req, res) => {
|
|
try {
|
|
const custa = await custaProcessualRepository.update(
|
|
req.params.id,
|
|
req.body,
|
|
);
|
|
res.json(custa);
|
|
} catch (error) {
|
|
res.status(500).json({ error: "Erro ao atualizar custa processual" });
|
|
}
|
|
});
|
|
|
|
app.delete("/api/custas/:id", async (req, res) => {
|
|
try {
|
|
await custaProcessualRepository.delete(req.params.id);
|
|
res.json({ message: "Custa processual excluída com sucesso" });
|
|
} catch (error) {
|
|
res.status(500).json({ error: "Erro ao excluir custa processual" });
|
|
}
|
|
});
|
|
|
|
// Honorários
|
|
app.get("/api/processos/:id/honorarios", async (req, res) => {
|
|
try {
|
|
const honorarios = await honorarioRepository.findByProcesso(req.params.id);
|
|
res.json(honorarios);
|
|
} catch (error) {
|
|
res.status(500).json({ error: "Erro ao buscar honorários" });
|
|
}
|
|
});
|
|
|
|
app.post("/api/processos/:id/honorarios", async (req, res) => {
|
|
try {
|
|
console.log("Dados recebidos para criar honorário:", req.body);
|
|
const honorario = await honorarioRepository.create({
|
|
...req.body,
|
|
processoId: req.params.id,
|
|
});
|
|
res.json(honorario);
|
|
} catch (error) {
|
|
console.error("Erro ao criar honorário:", error);
|
|
res.status(500).json({
|
|
error: "Erro ao criar honorário",
|
|
details: error instanceof Error ? error.message : "Erro desconhecido",
|
|
});
|
|
}
|
|
});
|
|
|
|
app.put("/api/honorarios/:id", async (req, res) => {
|
|
try {
|
|
const honorario = await honorarioRepository.update(req.params.id, req.body);
|
|
res.json(honorario);
|
|
} catch (error) {
|
|
res.status(500).json({ error: "Erro ao atualizar honorário" });
|
|
}
|
|
});
|
|
|
|
app.delete("/api/honorarios/:id", async (req, res) => {
|
|
try {
|
|
await honorarioRepository.delete(req.params.id);
|
|
res.json({ message: "Honorário excluído com sucesso" });
|
|
} catch (error) {
|
|
res.status(500).json({ error: "Erro ao excluir honorário" });
|
|
}
|
|
});
|
|
|
|
// Mover esta rota ANTES das rotas com parâmetros genéricos
|
|
app.put("/api/honorarios/parcelas/:id", async (req, res) => {
|
|
try {
|
|
console.log("Atualizando parcela:", req.params.id, req.body);
|
|
|
|
const result = await honorarioRepository.updateParcela(req.params.id, {
|
|
status: req.body.status,
|
|
valorPago: req.body.valorPago ? Number(req.body.valorPago) : null,
|
|
dataPagamento: req.body.dataPagamento
|
|
? new Date(req.body.dataPagamento)
|
|
: null,
|
|
comprovante: req.body.comprovante,
|
|
observacoes: req.body.observacoes,
|
|
});
|
|
|
|
res.json(result);
|
|
} catch (error) {
|
|
console.error("Erro ao atualizar parcela:", error);
|
|
res.status(500).json({ error: "Erro ao atualizar parcela" });
|
|
}
|
|
});
|
|
|
|
// Adicionar rota para proxy do DataJud
|
|
app.post("/api/datajud/consulta", async (req, res) => {
|
|
try {
|
|
const { numeroProcesso, tribunal } = req.body;
|
|
const API_KEY = process.env.DATAJUD_API_KEY;
|
|
const tribunalLowerCase = tribunal.toLowerCase().replace("_", "");
|
|
|
|
console.log("Consultando DataJud:", {
|
|
numeroProcesso,
|
|
tribunal: tribunalLowerCase,
|
|
url: `https://api-publica.datajud.cnj.jus.br/api_publica_${tribunalLowerCase}/_search`,
|
|
});
|
|
|
|
const response = await axios.post(
|
|
`https://api-publica.datajud.cnj.jus.br/api_publica_${tribunalLowerCase}/_search`,
|
|
{
|
|
query: {
|
|
match: {
|
|
numeroProcesso,
|
|
},
|
|
},
|
|
},
|
|
{
|
|
headers: {
|
|
Authorization: `APIKey ${API_KEY}`,
|
|
"Content-Type": "application/json",
|
|
},
|
|
},
|
|
);
|
|
|
|
res.json(response.data);
|
|
} catch (error: any) {
|
|
console.error(
|
|
"Erro na consulta ao DataJud:",
|
|
error.response?.data || error.message,
|
|
);
|
|
res.status(500).json({
|
|
error: "Erro ao consultar DataJud",
|
|
details: error.response?.data || error.message,
|
|
});
|
|
}
|
|
});
|
|
|
|
// Rotas de Usuários
|
|
app.get("/api/usuarios", async (req, res) => {
|
|
try {
|
|
const usuarios = await prisma.usuario.findMany({
|
|
select: {
|
|
id: true,
|
|
nome: true,
|
|
email: true,
|
|
perfil: true,
|
|
cpf: true,
|
|
rg: true,
|
|
oab: true,
|
|
oabUF: true,
|
|
telefone: true,
|
|
endereco: true,
|
|
numero: true,
|
|
complemento: true,
|
|
bairro: true,
|
|
cidade: true,
|
|
estado: true,
|
|
cep: true,
|
|
ativo: true,
|
|
dataCriacao: true,
|
|
},
|
|
});
|
|
res.json(usuarios);
|
|
} catch (error) {
|
|
res.status(500).json({ error: "Erro ao buscar usuários" });
|
|
}
|
|
});
|
|
|
|
app.post("/api/usuarios", async (req, res) => {
|
|
try {
|
|
const dados = {
|
|
...req.body,
|
|
senha: await bcrypt.hash(req.body.senha, 10),
|
|
};
|
|
|
|
const usuario = await prisma.usuario.create({
|
|
data: dados,
|
|
select: {
|
|
id: true,
|
|
nome: true,
|
|
email: true,
|
|
perfil: true,
|
|
cpf: true,
|
|
rg: true,
|
|
oab: true,
|
|
oabUF: true,
|
|
telefone: true,
|
|
endereco: true,
|
|
numero: true,
|
|
complemento: true,
|
|
bairro: true,
|
|
cidade: true,
|
|
estado: true,
|
|
cep: true,
|
|
ativo: true,
|
|
dataCriacao: true,
|
|
},
|
|
});
|
|
res.status(201).json(usuario);
|
|
} catch (error) {
|
|
res.status(400).json({ error: "Erro ao criar usuário" });
|
|
}
|
|
});
|
|
|
|
// Adicionar middleware para verificar campos protegidos
|
|
const protectFields = (req, res, next) => {
|
|
const protectedFields = ["perfil", "cpf"];
|
|
protectedFields.forEach((field) => {
|
|
delete req.body[field];
|
|
});
|
|
next();
|
|
};
|
|
|
|
// Atualizar rota de update de usuário
|
|
app.put("/api/usuarios/:id", protectFields, async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
const token = req.headers.authorization?.replace("Bearer ", "");
|
|
const decoded = jwt.verify(token, process.env.JWT_SECRET) as any;
|
|
|
|
// Verificar se o usuário está atualizando seu próprio perfil
|
|
if (id !== decoded.id) {
|
|
return res.status(403).json({ error: "Não autorizado" });
|
|
}
|
|
|
|
const dados = { ...req.body };
|
|
|
|
if (dados.senha) {
|
|
dados.senha = await bcrypt.hash(dados.senha, 10);
|
|
} else {
|
|
delete dados.senha;
|
|
}
|
|
|
|
const usuario = await prisma.usuario.update({
|
|
where: { id },
|
|
data: dados,
|
|
select: {
|
|
id: true,
|
|
nome: true,
|
|
email: true,
|
|
perfil: true,
|
|
cpf: true,
|
|
rg: true,
|
|
oab: true,
|
|
oabUF: true,
|
|
telefone: true,
|
|
endereco: true,
|
|
numero: true,
|
|
complemento: true,
|
|
bairro: true,
|
|
cidade: true,
|
|
estado: true,
|
|
cep: true,
|
|
ativo: true,
|
|
dataCriacao: true,
|
|
},
|
|
});
|
|
res.json(usuario);
|
|
} catch (error) {
|
|
console.error("Erro ao atualizar usuário:", error);
|
|
res.status(400).json({ error: "Erro ao atualizar usuário" });
|
|
}
|
|
});
|
|
|
|
// Nova rota DELETE para remover usuário
|
|
app.delete("/api/usuarios/:id", async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
await prisma.usuario.delete({ where: { id } });
|
|
res.status(204).send();
|
|
} catch (error) {
|
|
console.error("Erro ao excluir usuário:", error);
|
|
res.status(400).json({ error: "Erro ao excluir usuário" });
|
|
}
|
|
});
|
|
|
|
// Rota para buscar usuário específico
|
|
app.get("/api/usuarios/:id", async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
const token = req.headers.authorization?.replace("Bearer ", "");
|
|
const decoded = jwt.verify(
|
|
token,
|
|
process.env.JWT_SECRET || "default-secret",
|
|
) as any;
|
|
|
|
// Verificar se o usuário está buscando seu próprio perfil ou é admin
|
|
const requestingUser = await prisma.usuario.findUnique({
|
|
where: { id: decoded.id },
|
|
select: { perfil: true },
|
|
});
|
|
|
|
if (id !== decoded.id && requestingUser?.perfil !== "ADVOGADO_ADMIN") {
|
|
return res.status(403).json({ error: "Não autorizado" });
|
|
}
|
|
|
|
const usuario = await prisma.usuario.findUnique({
|
|
where: { id },
|
|
select: {
|
|
id: true,
|
|
nome: true,
|
|
email: true,
|
|
perfil: true,
|
|
cpf: true,
|
|
rg: true,
|
|
oab: true,
|
|
oabUF: true,
|
|
telefone: true,
|
|
endereco: true,
|
|
numero: true,
|
|
complemento: true,
|
|
bairro: true,
|
|
cidade: true,
|
|
estado: true,
|
|
cep: true,
|
|
ativo: true,
|
|
dataCriacao: true,
|
|
},
|
|
});
|
|
|
|
if (!usuario) {
|
|
return res.status(404).json({ error: "Usuário não encontrado" });
|
|
}
|
|
res.json(usuario);
|
|
} catch (error) {
|
|
console.error("Erro ao buscar usuário:", error);
|
|
res.status(500).json({ error: "Erro ao buscar usuário" });
|
|
}
|
|
});
|
|
|
|
// Adicionar rota para alternar status do usuário
|
|
app.patch("/api/usuarios/:id/status", async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
const { ativo } = req.body;
|
|
|
|
// Verificar se o usuário que faz a requisição é admin
|
|
const token = req.headers.authorization?.replace("Bearer ", "");
|
|
const decoded = jwt.verify(token, process.env.JWT_SECRET) as any;
|
|
|
|
const requestingUser = await prisma.usuario.findUnique({
|
|
where: { id: decoded.id },
|
|
select: { perfil: true },
|
|
});
|
|
|
|
if (requestingUser?.perfil !== "ADVOGADO_ADMIN") {
|
|
return res.status(403).json({ error: "Não autorizado" });
|
|
}
|
|
|
|
const usuario = await prisma.usuario.update({
|
|
where: { id },
|
|
data: { ativo },
|
|
select: {
|
|
id: true,
|
|
nome: true,
|
|
email: true,
|
|
perfil: true,
|
|
cpf: true,
|
|
rg: true,
|
|
oab: true,
|
|
oabUF: true,
|
|
telefone: true,
|
|
endereco: true,
|
|
numero: true,
|
|
complemento: true,
|
|
bairro: true,
|
|
cidade: true,
|
|
estado: true,
|
|
cep: true,
|
|
ativo: true,
|
|
},
|
|
});
|
|
res.json(usuario);
|
|
} catch (error) {
|
|
console.error("Erro ao atualizar status do usuário:", error);
|
|
res.status(400).json({ error: "Erro ao atualizar status do usuário" });
|
|
}
|
|
});
|
|
|
|
// Rotas de Atendimentos
|
|
app.get("/api/atendimentos", async (req, res) => {
|
|
try {
|
|
const atendimentos = await prisma.atendimento.findMany({
|
|
include: {
|
|
cliente: true,
|
|
processo: true,
|
|
usuario: {
|
|
select: {
|
|
id: true,
|
|
nome: true,
|
|
},
|
|
},
|
|
anexos: true,
|
|
},
|
|
orderBy: {
|
|
dataAtendimento: 'desc',
|
|
},
|
|
});
|
|
res.json(atendimentos);
|
|
} catch (error) {
|
|
console.error("Erro ao buscar atendimentos:", error);
|
|
res.status(500).json({ error: "Erro ao buscar atendimentos" });
|
|
}
|
|
});
|
|
|
|
app.post("/api/atendimentos", authMiddleware, async (req, res) => {
|
|
try {
|
|
const { clienteId, processoId, tipo, titulo, conteudo, agendamentoId } = req.body;
|
|
|
|
if (!req.user?.id) {
|
|
return res.status(401).json({ error: "Usuário não autenticado" });
|
|
}
|
|
|
|
if (!clienteId) {
|
|
return res.status(400).json({ error: "ClienteId é obrigatório" });
|
|
}
|
|
|
|
// Verificar se o cliente existe
|
|
const clienteExiste = await prisma.cliente.findUnique({
|
|
where: { id: clienteId }
|
|
});
|
|
|
|
if (!clienteExiste) {
|
|
return res.status(400).json({ error: "Cliente não encontrado" });
|
|
}
|
|
|
|
// Gerar protocolo
|
|
const ano = new Date().getFullYear();
|
|
const ultimoProtocolo = await prisma.atendimento.findFirst({
|
|
where: {
|
|
protocolo: {
|
|
startsWith: `${ano}/`,
|
|
},
|
|
},
|
|
orderBy: {
|
|
protocolo: 'desc',
|
|
},
|
|
});
|
|
|
|
const numeroSequencial = ultimoProtocolo
|
|
? parseInt(ultimoProtocolo.protocolo.split('/')[1]) + 1
|
|
: 1;
|
|
const protocolo = `${ano}/${numeroSequencial.toString().padStart(6, '0')}`;
|
|
|
|
// Criar atendimento usando transaction
|
|
const atendimento = await prisma.$transaction(async (tx) => {
|
|
// Criar o atendimento primeiro
|
|
const atendimento = await tx.atendimento.create({
|
|
data: {
|
|
protocolo,
|
|
titulo,
|
|
tipo: tipo as TipoAtendimento,
|
|
conteudo,
|
|
cliente: { connect: { id: clienteId } },
|
|
usuario: { connect: { id: req.user!.id } },
|
|
...(processoId && { processo: { connect: { id: processoId } } }), // Adicionar vírgula aqui
|
|
status: 'ATIVO',
|
|
dataAtualizacao: new Date()
|
|
},
|
|
include: {
|
|
cliente: true,
|
|
processo: true,
|
|
usuario: {
|
|
select: {
|
|
id: true,
|
|
nome: true,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
// Se houver agendamentoId, atualizar o agendamento
|
|
if (agendamentoId) {
|
|
await tx.agendamentoAtendimento.update({
|
|
where: { id: agendamentoId },
|
|
data: {
|
|
status: 'REALIZADO',
|
|
atendimento: { connect: { id: atendimento.id } },
|
|
},
|
|
});
|
|
}
|
|
|
|
return atendimento;
|
|
});
|
|
|
|
res.status(201).json(atendimento);
|
|
} catch (error) {
|
|
console.error("Erro ao criar atendimento:", error);
|
|
res.status(400).json({
|
|
error: "Erro ao criar atendimento",
|
|
details: error instanceof Error ? error.message : "Erro desconhecido"
|
|
});
|
|
}
|
|
});
|
|
|
|
// Adicionar nova rota para buscar atendimentos iniciais de um cliente
|
|
app.get("/api/atendimentos/iniciais/:clienteId", async (req, res) => {
|
|
try {
|
|
const { clienteId } = req.params;
|
|
const atendimentosIniciais = await prisma.atendimento.findMany({
|
|
where: {
|
|
clienteId,
|
|
tipo: TipoAtendimento.INICIAL,
|
|
},
|
|
orderBy: {
|
|
dataAtendimento: 'desc',
|
|
},
|
|
});
|
|
res.json(atendimentosIniciais);
|
|
} catch (error) {
|
|
console.error("Erro ao buscar atendimentos iniciais:", error);
|
|
res.status(500).json({ error: "Erro ao buscar atendimentos iniciais" });
|
|
}
|
|
});
|
|
|
|
// Adicionar rota de busca de clientes
|
|
app.get("/api/clientes/search", async (req, res) => {
|
|
try {
|
|
const { q } = req.query;
|
|
if (!q || typeof q !== 'string' || q.length < 3) {
|
|
return res.status(400).json({ error: "Termo de busca inválido" });
|
|
}
|
|
|
|
const clientes = await prisma.cliente.findMany({
|
|
where: {
|
|
OR: [
|
|
{ nome: { contains: q, mode: 'insensitive' } },
|
|
{ cpfCnpj: { contains: q } },
|
|
{ email: { contains: q, mode: 'insensitive' } }
|
|
]
|
|
},
|
|
take: 10,
|
|
});
|
|
|
|
res.json(clientes);
|
|
} catch (error) {
|
|
console.error("Erro na busca de clientes:", error);
|
|
res.status(500).json({ error: "Erro ao buscar clientes" });
|
|
}
|
|
});
|
|
|
|
// Modificar a rota de criação de atendimento para incluir atendimentoInicialId
|
|
app.post("/api/atendimentos", authMiddleware, async (req, res) => {
|
|
try {
|
|
const { clienteId, processoId, tipo, titulo, conteudo, atendimentoInicialId } = req.body;
|
|
|
|
if (!req.user?.id) {
|
|
return res.status(401).json({ error: "Usuário não autenticado" });
|
|
}
|
|
|
|
if (!clienteId) {
|
|
return res.status(400).json({ error: "ClienteId é obrigatório" });
|
|
}
|
|
|
|
// Validar se existe atendimentoInicialId quando não for INICIAL
|
|
if (tipo !== TipoAtendimento.INICIAL && !atendimentoInicialId) {
|
|
return res.status(400).json({ error: "Atendimento inicial é obrigatório para retornos e encaminhamentos" });
|
|
}
|
|
|
|
const ano = new Date().getFullYear();
|
|
const ultimoProtocolo = await prisma.atendimento.findFirst({
|
|
where: { protocolo: { startsWith: `${ano}/` } },
|
|
orderBy: { protocolo: 'desc' },
|
|
});
|
|
|
|
const numeroSequencial = ultimoProtocolo
|
|
? parseInt(ultimoProtocolo.protocolo.split('/')[1]) + 1
|
|
: 1;
|
|
const protocolo = `${ano}/${numeroSequencial.toString().padStart(6, '0')}`;
|
|
|
|
const data = {
|
|
protocolo,
|
|
titulo,
|
|
tipo,
|
|
conteudo,
|
|
clienteId,
|
|
processoId,
|
|
usuarioId: req.user.id,
|
|
...(atendimentoInicialId && { atendimentoInicialId }),
|
|
};
|
|
|
|
const atendimento = await prisma.atendimento.create({
|
|
data,
|
|
include: {
|
|
cliente: true,
|
|
processo: true,
|
|
usuario: {
|
|
select: {
|
|
id: true,
|
|
nome: true,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
res.status(201).json(atendimento);
|
|
} catch (error) {
|
|
console.error("Erro ao criar atendimento:", error);
|
|
res.status(400).json({
|
|
error: "Erro ao criar atendimento",
|
|
details: error instanceof Error ? error.message : "Erro desconhecido"
|
|
});
|
|
}
|
|
});
|
|
|
|
// Adicionar rota para buscar atendimento específico
|
|
app.get("/api/atendimentos/:id", async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
const atendimento = await prisma.atendimento.findUnique({
|
|
where: { id },
|
|
include: {
|
|
cliente: true,
|
|
processo: true,
|
|
usuario: {
|
|
select: {
|
|
id: true,
|
|
nome: true,
|
|
},
|
|
},
|
|
anexos: true,
|
|
atendimentoInicial: true,
|
|
atendimentosRelacionados: {
|
|
include: {
|
|
usuario: {
|
|
select: {
|
|
id: true,
|
|
nome: true,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
},
|
|
});
|
|
|
|
if (!atendimento) {
|
|
return res.status(404).json({ error: "Atendimento não encontrado" });
|
|
}
|
|
|
|
res.json(atendimento);
|
|
} catch (error) {
|
|
console.error("Erro ao buscar atendimento:", error);
|
|
res.status(500).json({ error: "Erro ao buscar atendimento" });
|
|
}
|
|
});
|
|
|
|
// Rotas de Agendamento
|
|
app.get("/api/agendamentos", async (req, res) => {
|
|
try {
|
|
const { data } = req.query;
|
|
const where = data ? {
|
|
data: {
|
|
gte: new Date(data as string),
|
|
lt: new Date(new Date(data as string).setDate(new Date(data as string).getDate() + 1))
|
|
}
|
|
} : {};
|
|
|
|
const agendamentos = await prisma.agendamentoAtendimento.findMany({
|
|
where,
|
|
include: {
|
|
cliente: true,
|
|
usuario: {
|
|
select: {
|
|
id: true,
|
|
nome: true,
|
|
},
|
|
},
|
|
atendimento: {
|
|
select: {
|
|
id: true,
|
|
protocolo: true,
|
|
titulo: true,
|
|
},
|
|
},
|
|
},
|
|
orderBy: {
|
|
data: 'asc',
|
|
},
|
|
});
|
|
res.json(agendamentos);
|
|
} catch (error) {
|
|
console.error("Erro ao buscar agendamentos:", error);
|
|
res.status(500).json({ error: "Erro ao buscar agendamentos" });
|
|
}
|
|
});
|
|
|
|
app.post("/api/agendamentos", authMiddleware, async (req, res) => {
|
|
try {
|
|
const { clienteId, data, observacoes } = req.body;
|
|
|
|
if (!req.user?.id) {
|
|
return res.status(401).json({ error: "Usuário não autenticado" });
|
|
}
|
|
|
|
const agendamento = await prisma.agendamentoAtendimento.create({
|
|
data: {
|
|
clienteId,
|
|
usuarioId: req.user.id,
|
|
data: new Date(data),
|
|
observacoes,
|
|
},
|
|
include: {
|
|
cliente: true,
|
|
usuario: {
|
|
select: {
|
|
id: true,
|
|
nome: true,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
res.status(201).json(agendamento);
|
|
} catch (error) {
|
|
console.error("Erro ao criar agendamento:", error);
|
|
res.status(400).json({ error: "Erro ao criar agendamento" });
|
|
}
|
|
});
|
|
|
|
app.patch("/api/agendamentos/:id/status", authMiddleware, async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
const { status } = req.body;
|
|
|
|
const agendamento = await prisma.agendamentoAtendimento.update({
|
|
where: { id },
|
|
data: { status },
|
|
include: {
|
|
cliente: true,
|
|
usuario: {
|
|
select: {
|
|
id: true,
|
|
nome: true,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
res.json(agendamento);
|
|
} catch (error) {
|
|
console.error("Erro ao atualizar status do agendamento:", error);
|
|
res.status(400).json({ error: "Erro ao atualizar status do agendamento" });
|
|
}
|
|
});
|
|
|
|
// Adicionar rotas de atualização e exclusão de agendamentos
|
|
app.put("/api/agendamentos/:id", authMiddleware, async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
const { clienteId, data, observacoes, tipo } = req.body;
|
|
|
|
const agendamento = await prisma.agendamentoAtendimento.update({
|
|
where: { id },
|
|
data: {
|
|
clienteId,
|
|
data: new Date(data),
|
|
observacoes,
|
|
tipo,
|
|
},
|
|
include: {
|
|
cliente: true,
|
|
usuario: {
|
|
select: {
|
|
id: true,
|
|
nome: true,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
res.json(agendamento);
|
|
} catch (error) {
|
|
console.error("Erro ao atualizar agendamento:", error);
|
|
res.status(400).json({ error: "Erro ao atualizar agendamento" });
|
|
}
|
|
});
|
|
|
|
app.delete("/api/agendamentos/:id", authMiddleware, async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
|
|
await prisma.agendamentoAtendimento.delete({
|
|
where: { id },
|
|
});
|
|
|
|
res.status(204).send();
|
|
} catch (error) {
|
|
console.error("Erro ao excluir agendamento:", error);
|
|
res.status(400).json({ error: "Erro ao excluir agendamento" });
|
|
}
|
|
});
|
|
|
|
// Atualizar a rota de agendamentos
|
|
app.get("/api/atendimentos/agendamentos", async (req, res) => {
|
|
try {
|
|
const { data } = req.query;
|
|
|
|
if (!data || typeof data !== 'string') {
|
|
return res.status(400).json({ error: 'Data inválida' });
|
|
}
|
|
|
|
const dataConsulta = new Date(data);
|
|
|
|
// Validar se a data é válida
|
|
if (isNaN(dataConsulta.getTime())) {
|
|
return res.status(400).json({ error: 'Formato de data inválido' });
|
|
}
|
|
|
|
// Definir início e fim do dia
|
|
const inicioDia = new Date(dataConsulta.setHours(0, 0, 0, 0));
|
|
const fimDia = new Date(dataConsulta.setHours(23, 59, 59, 999));
|
|
|
|
// Buscar na tabela correta com filtros apropriados
|
|
const agendamentos = await prisma.agendamentoAtendimento.findMany({
|
|
where: {
|
|
data: {
|
|
gte: inicioDia,
|
|
lte: fimDia
|
|
}
|
|
},
|
|
include: {
|
|
cliente: {
|
|
select: {
|
|
id: true,
|
|
nome: true,
|
|
cpfCnpj: true,
|
|
telefone: true
|
|
}
|
|
},
|
|
usuario: {
|
|
select: {
|
|
id: true,
|
|
nome: true
|
|
}
|
|
}
|
|
},
|
|
orderBy: {
|
|
data: 'asc'
|
|
}
|
|
});
|
|
|
|
// Filtrar apenas agendamentos com UUIDs válidos
|
|
const validAgendamentos = agendamentos.filter(agendamento =>
|
|
isValidUUID(agendamento.id) &&
|
|
isValidUUID(agendamento.clienteId) &&
|
|
isValidUUID(agendamento.usuarioId)
|
|
);
|
|
|
|
console.log(`Encontrados ${validAgendamentos.length} agendamentos válidos para ${data}`);
|
|
|
|
res.json(validAgendamentos);
|
|
} catch (error) {
|
|
console.error('Erro ao buscar agendamentos:', error);
|
|
res.status(500).json({
|
|
error: 'Erro ao buscar agendamentos',
|
|
details: error instanceof Error ? error.message : 'Erro desconhecido'
|
|
});
|
|
}
|
|
});
|
|
|
|
// Erro handling middleware
|
|
app.use(
|
|
(
|
|
err: Error,
|
|
req: express.Request,
|
|
res: express.Response,
|
|
next: express.NextFunction,
|
|
) => {
|
|
console.error(err.stack);
|
|
res.status(500).json({ error: "Erro interno do servidor" });
|
|
},
|
|
);
|
|
|
|
// Aumentar timeout do servidor para operações longas (ex: PDF, OCR)
|
|
const server = app.listen(port, () => {
|
|
console.log(`🚀 Servidor rodando em http://localhost:${port}`);
|
|
|
|
// Pré-aquece o worker Tesseract OCR em background (elimina delay na primeira operação)
|
|
PDFService.warmupOCR('por').catch(() => {});
|
|
});
|
|
server.timeout = 600000; // 10 minutos (600 segundos)
|
|
|
|
// Encerra workers Tesseract ao desligar o servidor
|
|
process.on('SIGTERM', async () => {
|
|
console.log('Encerrando workers OCR...');
|
|
await PDFService.terminateWorkers();
|
|
process.exit(0);
|
|
});
|
|
|
|
process.on('SIGINT', async () => {
|
|
console.log('Encerrando workers OCR...');
|
|
await PDFService.terminateWorkers();
|
|
process.exit(0);
|
|
});
|
|
|
|
process.on("unhandledRejection", (err) => {
|
|
console.error("Erro não tratado:", err);
|
|
});
|
|
|
|
app.patch("/api/atendimentos/:id/status", authMiddleware, async (req, res) => {
|
|
try {
|
|
const { id } = req.params;
|
|
const { status, justificativa } = req.body;
|
|
|
|
const atendimento = await prisma.atendimento.update({
|
|
where: { id },
|
|
data: {
|
|
status,
|
|
justificativaCancelamento: status === 'CANCELADO' ? justificativa : null,
|
|
dataAtualizacao: new Date()
|
|
},
|
|
include: {
|
|
cliente: true,
|
|
usuario: {
|
|
select: {
|
|
id: true,
|
|
nome: true,
|
|
},
|
|
},
|
|
},
|
|
});
|
|
|
|
res.json(atendimento);
|
|
} catch (error) {
|
|
console.error("Erro ao atualizar status do atendimento:", error);
|
|
res.status(400).json({ error: "Erro ao atualizar status do atendimento" });
|
|
}
|
|
});
|
|
|
|
// Mover estas rotas para o início, antes das outras
|
|
app.use('/api/anexos', anexosRoutes);
|
|
app.use('/api/atendimentos', atendimentosRoutes);
|
|
app.use('/api/provas', provasRouter);
|
|
|
|
app.use('/api/tarefas', tarefasRoutes);
|
|
app.use('/api/dashboard', authMiddleware, dashboardRoutes);
|
|
app.use('/api/documentos', documentosRouter);
|
|
app.use('/api/documentos-modelos', documentosModelosRouter);
|
|
app.use('/api/processos-administrativos', processosAdministrativosRoutes);
|
|
app.use('/api/calculos', calculosJudiciaisRoutes);
|
|
app.use('/api/indices', indicesMonetariosRoutes);
|
|
app.use('/api/pensao-alimenticia', pensaoAlimenticiaRouter);
|
|
app.use('/api/financeiro-painel', financeiroPainelRoutes); // Adicionar uso das rotas do financeiro painel
|
|
app.use('/api/audiencias', audienciasRoutes); // Adicionar uso das rotas de audiências
|
|
app.use('/api/pdf', pdfRoutes); // Adicionar uso das rotas de PDF
|