357 lines
8.4 KiB
JavaScript
357 lines
8.4 KiB
JavaScript
const movimentosService = require('../services/movimentos.service');
|
|
|
|
const MOVIMENTOS_VALIDOS = ['Entrada', 'Saida', 'Sangria', 'Estorno'];
|
|
const STATUS_VALIDOS = ['Pago', 'A pagar', 'Recebido', 'A receber'];
|
|
|
|
function validarStatusPorMovimento(movimento, status) {
|
|
if (movimento === 'Entrada' || movimento === 'Estorno') {
|
|
return ['A receber', 'Recebido'].includes(status);
|
|
}
|
|
|
|
if (movimento === 'Saida') {
|
|
return ['A pagar', 'Pago'].includes(status);
|
|
}
|
|
|
|
if (movimento === 'Sangria') {
|
|
return status === 'Pago';
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function validarDadosMovimento(dados) {
|
|
if (!dados.movimento) {
|
|
return 'Movimento é obrigatório.';
|
|
}
|
|
|
|
if (!MOVIMENTOS_VALIDOS.includes(dados.movimento)) {
|
|
return 'Movimento inválido.';
|
|
}
|
|
|
|
if (!dados.descricao || !String(dados.descricao).trim()) {
|
|
return 'Descrição é obrigatória.';
|
|
}
|
|
|
|
if (dados.valor === undefined || dados.valor === null || dados.valor === '') {
|
|
return 'Valor é obrigatório.';
|
|
}
|
|
|
|
const valor = Number(dados.valor);
|
|
|
|
if (!Number.isFinite(valor)) {
|
|
return 'Valor inválido.';
|
|
}
|
|
|
|
if (valor <= 0) {
|
|
return 'Valor deve ser maior que zero.';
|
|
}
|
|
|
|
if (!dados.status) {
|
|
return 'Situação é obrigatória.';
|
|
}
|
|
|
|
if (!STATUS_VALIDOS.includes(dados.status)) {
|
|
return 'Situação inválida.';
|
|
}
|
|
|
|
if (!validarStatusPorMovimento(dados.movimento, dados.status)) {
|
|
return 'Situação incompatível com o tipo de movimento.';
|
|
}
|
|
|
|
if (!dados.dataentrada) {
|
|
return 'Data de entrada é obrigatória.';
|
|
}
|
|
|
|
if (!dados.datavencimento) {
|
|
return 'Data de vencimento é obrigatória.';
|
|
}
|
|
|
|
const parcela = Number(dados.parcela || 1);
|
|
const parcelas = Number(dados.parcelas || 1);
|
|
|
|
if (!Number.isInteger(parcela) || parcela < 1) {
|
|
return 'Parcela inválida.';
|
|
}
|
|
|
|
if (!Number.isInteger(parcelas) || parcelas < 1) {
|
|
return 'Quantidade de parcelas inválida.';
|
|
}
|
|
|
|
if (parcela > parcelas) {
|
|
return 'Parcela atual não pode ser maior que o total de parcelas.';
|
|
}
|
|
|
|
if (dados.movimento === 'Sangria') {
|
|
if (!dados.idbancos) {
|
|
return 'Banco de origem é obrigatório para sangria.';
|
|
}
|
|
|
|
if (!dados.idbancos_p) {
|
|
return 'Banco de destino é obrigatório para sangria.';
|
|
}
|
|
|
|
if (Number(dados.idbancos) === Number(dados.idbancos_p)) {
|
|
return 'Banco de origem e destino não podem ser iguais.';
|
|
}
|
|
}
|
|
|
|
if (dados.modoParcelamento && !['valor_parcela', 'valor_total'].includes(dados.modoParcelamento)) {
|
|
return 'Modo de parcelamento inválido.';
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
function tratarErro(error, res, mensagemPadrao) {
|
|
if (error?.code === 'DUPLICIDADE_MOVIMENTO') {
|
|
return res.status(409).json({
|
|
ok: false,
|
|
requiresConfirmation: true,
|
|
message: error.message,
|
|
data: error.data,
|
|
});
|
|
}
|
|
|
|
return res.status(500).json({
|
|
ok: false,
|
|
message: mensagemPadrao,
|
|
});
|
|
}
|
|
|
|
async function listar(req, res) {
|
|
try {
|
|
const resultado = await movimentosService.listarMovimentos({
|
|
limite: req.query.limite,
|
|
offset: req.query.offset,
|
|
page: req.query.page,
|
|
busca: req.query.busca,
|
|
movimento: req.query.movimento,
|
|
status: req.query.status,
|
|
idbancos: req.query.idbancos,
|
|
idcentrodecustos: req.query.idcentrodecustos,
|
|
idclientes: req.query.idclientes,
|
|
idbancos_p: req.query.idbancos_p,
|
|
idmovimentosfixos: req.query.idmovimentosfixos,
|
|
competencia: req.query.competencia,
|
|
grupo_parcelamento: req.query.grupo_parcelamento,
|
|
origem: req.query.origem,
|
|
saldo_processado: req.query.saldo_processado,
|
|
referenciaTipo: req.query.referenciaTipo,
|
|
dataCampo: req.query.dataCampo,
|
|
dataInicio: req.query.dataInicio,
|
|
dataFim: req.query.dataFim,
|
|
incluirExcluidos: req.query.incluirExcluidos,
|
|
orderBy: req.query.orderBy,
|
|
orderDirection: req.query.orderDirection,
|
|
|
|
idusuarios: req.user.idusuarios || req.user.id,
|
|
});
|
|
|
|
return res.json({
|
|
ok: true,
|
|
data: resultado.data,
|
|
pagination: resultado.pagination,
|
|
summary: resultado.summary,
|
|
});
|
|
} catch (error) {
|
|
console.error('Erro ao listar movimentos:', error);
|
|
|
|
return res.status(500).json({
|
|
ok: false,
|
|
message: 'Erro ao listar movimentos.',
|
|
});
|
|
}
|
|
}
|
|
|
|
async function buscarPorId(req, res) {
|
|
try {
|
|
const id = Number(req.params.id);
|
|
|
|
if (!id) {
|
|
return res.status(400).json({
|
|
ok: false,
|
|
message: 'ID inválido.',
|
|
});
|
|
}
|
|
|
|
const movimento = await movimentosService.buscarMovimentoPorId(id, {
|
|
idUsuario: req.user.idusuarios || req.user.id,
|
|
});
|
|
|
|
if (!movimento) {
|
|
return res.status(404).json({
|
|
ok: false,
|
|
message: 'Movimento não encontrado.',
|
|
});
|
|
}
|
|
|
|
return res.json({
|
|
ok: true,
|
|
data: movimento,
|
|
});
|
|
} catch (error) {
|
|
console.error('Erro ao buscar movimento:', error);
|
|
|
|
return res.status(500).json({
|
|
ok: false,
|
|
message: 'Erro ao buscar movimento.',
|
|
});
|
|
}
|
|
}
|
|
|
|
async function verificarDuplicidade(req, res) {
|
|
try {
|
|
const duplicado = await movimentosService.verificarDuplicidade(req.body);
|
|
|
|
return res.json({
|
|
ok: true,
|
|
data: duplicado,
|
|
});
|
|
} catch (error) {
|
|
console.error('Erro ao verificar duplicidade:', error);
|
|
|
|
return res.status(500).json({
|
|
ok: false,
|
|
message: 'Erro ao verificar duplicidade.',
|
|
});
|
|
}
|
|
}
|
|
|
|
async function preverImpactoSaldo(req, res) {
|
|
try {
|
|
const erroValidacao = validarDadosMovimento(req.body);
|
|
|
|
if (erroValidacao) {
|
|
return res.status(400).json({
|
|
ok: false,
|
|
message: erroValidacao,
|
|
});
|
|
}
|
|
|
|
const impacto = await movimentosService.preverImpactoSaldo(req.body, req.body.idcontasapagar);
|
|
|
|
return res.json({
|
|
ok: true,
|
|
data: impacto,
|
|
});
|
|
} catch (error) {
|
|
console.error('Erro ao prever impacto de saldo:', error);
|
|
|
|
return res.status(500).json({
|
|
ok: false,
|
|
message: 'Erro ao prever impacto de saldo.',
|
|
});
|
|
}
|
|
}
|
|
|
|
async function criar(req, res) {
|
|
try {
|
|
const erroValidacao = validarDadosMovimento(req.body);
|
|
|
|
if (erroValidacao) {
|
|
return res.status(400).json({
|
|
ok: false,
|
|
message: erroValidacao,
|
|
});
|
|
}
|
|
|
|
const resultado = await movimentosService.criarMovimento(req.user.id, req.body);
|
|
|
|
return res.status(201).json({
|
|
ok: true,
|
|
message: 'Movimento cadastrado com sucesso.',
|
|
data: resultado.data,
|
|
parcelasGeradas: resultado.parcelasGeradas || [],
|
|
impactoSaldo: resultado.impactoSaldo || [],
|
|
});
|
|
} catch (error) {
|
|
console.error('Erro ao criar movimento:', error);
|
|
return tratarErro(error, res, 'Erro ao criar movimento.');
|
|
}
|
|
}
|
|
|
|
async function atualizar(req, res) {
|
|
try {
|
|
const id = Number(req.params.id);
|
|
|
|
if (!id) {
|
|
return res.status(400).json({
|
|
ok: false,
|
|
message: 'ID inválido.',
|
|
});
|
|
}
|
|
|
|
const erroValidacao = validarDadosMovimento(req.body);
|
|
|
|
if (erroValidacao) {
|
|
return res.status(400).json({
|
|
ok: false,
|
|
message: erroValidacao,
|
|
});
|
|
}
|
|
|
|
const resultado = await movimentosService.atualizarMovimento(id, req.user.id, req.body);
|
|
|
|
if (!resultado?.data) {
|
|
return res.status(404).json({
|
|
ok: false,
|
|
message: 'Movimento não encontrado.',
|
|
});
|
|
}
|
|
|
|
return res.json({
|
|
ok: true,
|
|
message: 'Movimento atualizado com sucesso.',
|
|
data: resultado.data,
|
|
impactoSaldo: resultado.impactoSaldo || [],
|
|
});
|
|
} catch (error) {
|
|
console.error('Erro ao atualizar movimento:', error);
|
|
return tratarErro(error, res, 'Erro ao atualizar movimento.');
|
|
}
|
|
}
|
|
|
|
async function deletar(req, res) {
|
|
try {
|
|
const id = Number(req.params.id);
|
|
|
|
if (!id) {
|
|
return res.status(400).json({
|
|
ok: false,
|
|
message: 'ID inválido.',
|
|
});
|
|
}
|
|
|
|
const resultado = await movimentosService.deletarMovimento(id, req.user.id);
|
|
|
|
if (!resultado?.ok) {
|
|
return res.status(404).json({
|
|
ok: false,
|
|
message: 'Movimento não encontrado.',
|
|
});
|
|
}
|
|
|
|
return res.json({
|
|
ok: true,
|
|
message: 'Movimento excluído com sucesso.',
|
|
impactoSaldo: resultado.impactoSaldo || [],
|
|
});
|
|
} catch (error) {
|
|
console.error('Erro ao excluir movimento:', error);
|
|
|
|
return res.status(500).json({
|
|
ok: false,
|
|
message: 'Erro ao excluir movimento.',
|
|
});
|
|
}
|
|
}
|
|
|
|
module.exports = {
|
|
listar,
|
|
buscarPorId,
|
|
verificarDuplicidade,
|
|
preverImpactoSaldo,
|
|
criar,
|
|
atualizar,
|
|
deletar,
|
|
}; |